无意中绕过了 Python 的私有属性
Bypassing Python's private attributes inadvertently
我使用以下代码设法绕过了 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()
被定义为一个简单的 class 包含 PointGPS
的列表 points = property(getPoints, setPoints)
和 PointGPS()
包含 3坐标(纬度、经度、高度)。不过这一切在这里都不重要了。
我可以绕过 setter 没有警告是正常的吗?
Python 旨在对初学者友好,但这似乎不太友好,因为它可以非常快速地将格式错误的数据插入列表(不知道!)。
Python 对新手来说不是特别友好,但有一条规则是允许所有没有明确禁止的东西,很少有东西是禁止的。可变类型是可变的,句号。如果 API returns 是一个内部可变对象,它隐含地允许 API 的用户修改该对象。
话虽如此,这可能是问题,也可能不是问题。记录修改对象不受支持并可能导致意外行为通常就足够了。
它通常 Python 比试图防止 API 用户的错误操作更复杂。毕竟,猴子修补是允许的,就像使用 class 的任何所谓的 private 成员一样,前提是你能猜出他们的名字。
您实际上不是 "bypassing the setter" - 当您尝试设置 t.points
(即:t.points = []
)时调用 setter,而不是当您 [=22] =]改变列表return由setter编辑。
如果您不希望客户端代码改变列表,要么 return 一些不可变的结构(这将表明它不应该被改变)或者至少 return 一个副本列表的(然后仍然是可变的,但修改不会影响原始列表 - 请注意,这可能会让您的代码用户感到惊讶)。
注意:在您的代码片段中有这样的注释:
which will return the list by reference
如果您希望在 Python 中完成任何事情,请停止思考其他语言并了解 Python 的工作原理。 Python 中没有 "by reference" 或 "by value" 之类的东西,只有名称和对象。您的 getter 没有 "return the list by reference",它 return 是列表,句号。我强烈建议您read this reference article(是的,蹩脚的双关语,抱歉)更多关于 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()
被定义为一个简单的 class 包含 PointGPS
的列表 points = property(getPoints, setPoints)
和 PointGPS()
包含 3坐标(纬度、经度、高度)。不过这一切在这里都不重要了。
我可以绕过 setter 没有警告是正常的吗?
Python 旨在对初学者友好,但这似乎不太友好,因为它可以非常快速地将格式错误的数据插入列表(不知道!)。
Python 对新手来说不是特别友好,但有一条规则是允许所有没有明确禁止的东西,很少有东西是禁止的。可变类型是可变的,句号。如果 API returns 是一个内部可变对象,它隐含地允许 API 的用户修改该对象。
话虽如此,这可能是问题,也可能不是问题。记录修改对象不受支持并可能导致意外行为通常就足够了。
它通常 Python 比试图防止 API 用户的错误操作更复杂。毕竟,猴子修补是允许的,就像使用 class 的任何所谓的 private 成员一样,前提是你能猜出他们的名字。
您实际上不是 "bypassing the setter" - 当您尝试设置 t.points
(即:t.points = []
)时调用 setter,而不是当您 [=22] =]改变列表return由setter编辑。
如果您不希望客户端代码改变列表,要么 return 一些不可变的结构(这将表明它不应该被改变)或者至少 return 一个副本列表的(然后仍然是可变的,但修改不会影响原始列表 - 请注意,这可能会让您的代码用户感到惊讶)。
注意:在您的代码片段中有这样的注释:
which will return the list by reference
如果您希望在 Python 中完成任何事情,请停止思考其他语言并了解 Python 的工作原理。 Python 中没有 "by reference" 或 "by value" 之类的东西,只有名称和对象。您的 getter 没有 "return the list by reference",它 return 是列表,句号。我强烈建议您read this reference article(是的,蹩脚的双关语,抱歉)更多关于 Python 的名称和对象的概念。