无意中绕过Python的私有属性

2024-06-16 11:49:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用以下代码绕过了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()定义为一个简单类,其中包含一个由points = property(getPoints, setPoints)定义的PointGPS列表,PointGPS()包含3个坐标(纬度、经度、海拔)。但这一切在这里都无关紧要

我可以在没有警告的情况下绕过设置器是正常的吗?

Python被设计成对初学者友好的,但是这看起来不是很友好,因为它可以很快地将格式错误的数据插入到列表中(不知道!)


Tags: the代码which列表return定义callwill
2条回答

实际上,您并不是在“绕过setter”——当您试图设置t.points(即:t.points = [])时,setter被调用,而不是当您对setter返回的列表进行变异时

如果您不想让客户机代码改变列表,可以返回一些不可变的结构(这将表明它不应该被更改),或者至少返回一个列表的副本(该副本仍然是可变的,但是修改不会影响原始列表-请注意,这可能会让您的代码用户大吃一惊)

注意:在您的代码片段中有以下注释:

which will return the list by reference

如果您希望用Python完成任何事情,请不要用其他语言来思考,而是理解Python是如何工作的。Python中没有“按引用”或“按值”,只有名称和对象。getter不会“通过引用返回列表”,而是返回列表,句点。我强烈建议您read this reference article(是的,蹩脚的双关语,抱歉)了解更多关于Python的名称和对象的概念

Python对初学者并不特别友好,但有一条规则是,所有没有明确禁止的东西都是允许的,很少有东西是禁止的。可变类型是可变的,句号。如果一个API返回一个内部可变对象,它将隐含地允许API的用户修改该对象

尽管如此,这可能还是个问题。通常只需记录修改对象是不受支持的,并且可能导致意外行为

它通常比试图阻止API用户的错误操作更具python风格。毕竟,猴子补丁是允许的,就像使用类的任何所谓的私有成员一样,只要你能猜出它们的名字

相关问题 更多 >