无意中绕过了Python的私有属性

时间:2018-05-14 14:39:14

标签: python python-3.x class oop encapsulation

我设法使用以下代码绕过了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的设计初学者友好,但这看起来并不友好,因为将错误的数据插入列表非常快(不知道!)。

2 个答案:

答案 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用户的错误操作。毕竟,允许猴子修补,就像使用任何所谓的私人成员一样,只要你可以猜出他们的名字。