Обход личных атрибутов Python непреднамеренно - PullRequest
0 голосов
/ 14 мая 2018

Мне удалось обойти сеттер, используя следующий код:

t = TrajetGPS()

# will call t.getPoints(), which will return the list by reference
# we can then modify it at will, bypassing the setter
points = t.points 
points.append(PointGPS(0, 0, 0))
points.append(PointGPS(1, 1, 1))


print(t) # will show : Points : (0, 0, 0) (1, 1, 1)

TrajetGPS() определяется как простой класс, содержащий список PointGPS, определенный с помощью points = property(getPoints, setPoints), а PointGPS() содержит 3 координаты (широта, долгота, высота). Но все это здесь не имеет значения.

Это нормально, я могу обойти сеттер без предупреждения?

Python предназначен для начинающих, но это не очень удобно, так как он может очень быстро вставить искаженные данные в список (не зная!).

Ответы [ 2 ]

0 голосов
/ 14 мая 2018

Вы на самом деле НЕ «обходите установщик» - установщик вызывается, когда вы пытаетесь установить t.points (то есть: t.points = []), а не когда вы изменяете список, возвращаемый установщиком .

Если вы не хотите, чтобы код клиента изменял список, либо верните некоторую неизменяемую структуру (которая прояснит, что ее не следует изменять), либо, по крайней мере, верните копию списка (которая затем будет изменяемой) , но модификация не повлияет на исходный список - учтите, что это может удивить пользователей вашего кода).

Примечание: в вашем фрагменте кода есть этот комментарий:

, который вернет список по ссылке

Если вы надеетесь что-нибудь сделать в Python, перестаньте думать в терминах какого-то другого языка и поймите, как работает Python. В Python нет ничего похожего на «по ссылке» или «по значению», только имена и объекты. Ваш получатель не «возвращает список по ссылке», он возвращает список, точка. Я настоятельно рекомендую вашему прочитать эту справочную статью (да, хромая каламбур, извините), чтобы узнать больше о концепциях имен и объектов в Python.

0 голосов
/ 14 мая 2018

Python не особенно подходит для новичков, но одно правило состоит в том, что все, что не запрещено явно, разрешено, и некоторые вещи запрещены.Изменчивый тип изменчив, полная остановка.Если API возвращает внутренний изменяемый объект, это косвенно позволяет пользователю API изменять этот объект.

При этом это может быть или не быть проблемой.Часто достаточно документировать, что изменение объекта не поддерживается и может привести к неожиданному поведению.

Это часто более Pythonic, чем попытка предотвратить неправильные операции со стороны пользователя API.В конце концов, патчирование обезьян допускается, как и использование любых так называемых частных членов класса, при условии, что вы можете угадать их имя.

...