我设法使用以下代码绕过了setter:
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
的{{1}}列表,points = property(getPoints, setPoints)
和PointGPS()
包含3个坐标(纬度,经度,海拔高度) 。但这一切并不重要。
是否正常我可以在没有警告的情况下绕过设定者?
Python的设计初学者友好,但这看起来并不友好,因为将错误的数据插入列表非常快(不知道!)。
答案 0 :(得分:4)
你实际上不是"绕过二传手" - 当您尝试设置t.points
(即:t.points = []
)时调用setter,而不是在变更 setter返回的列表时调用。
如果您不希望客户端代码改变列表,请返回一些不可变结构(这将清楚表明它不应该被更改)或者至少返回列表的副本(然后它仍然是可变的,但修改不会影响原始列表 - 请注意,这可能会让您的代码用户感到惊讶。)
注意:在您的代码段中有以下评论:
将按引用返回列表
如果您希望在Python中完成任何工作,请停止使用其他语言进行思考,并了解Python的工作原理。没有什么比#34;参考"或者"按价值"在Python中,只有名称和对象。你的getter不会通过引用"返回列表,它返回列表,句点。我强烈建议您使用read this reference article(是的,蹩脚的双关语,对不起)了解Python的名称和对象概念。
答案 1 :(得分:3)
Python并不是特别适合初学者,但有一条规则是禁止明确禁止的所有内容,并禁止使用。可变类型是可变的,完全停止。如果API返回内部可变对象,则隐含地允许API的用户修改该对象。
话虽如此,它可能是也可能不是问题。通常可以记录修改对象不受支持并可能导致意外行为。
通常更多Pythonic而不是试图阻止API用户的错误操作。毕竟,允许猴子修补,就像使用任何所谓的私人成员一样,只要你可以猜出他们的名字。