以下代码:
class MyClass():
def test(self):
self.__x = 0
def __setattr__(self, name, value):
print name
def __getattr__(self, name):
print name
raise AttributeError(name)
x = MyClass()
x.test()
x.__y
输出:
_MyClass__x
__y
Traceback (most recent call last):
...
AttributeError: __y
文档完全没有用,说明“名称”是“属性的名称”,但由于某种原因,它取决于您是设置还是获取它。
我想知道的是:
x
而不是_MyClass__x
?答案 0 :(得分:4)
双下划线调用名称重整。如果您不需要名称修改,请不要使用双重非意外
What is the meaning of a single- and a double-underscore before an object name?
9.6。私人变量
在Python中不存在除了从对象内部访问之外无法访问的“私有”实例变量。但是,大多数Python代码都遵循一个约定:前缀为下划线的名称(例如
_spam
)应被视为API的非公共部分(无论是函数,方法还是数据成员)。它应被视为实施细节,如有更改,恕不另行通知。由于类私有成员有一个有效的用例(即为了避免名称与子类定义的名称冲突),对这种称为名称修改的机制的支持有限。表单
__spam
的任何标识符(至少两个前导下划线,最多一个尾随下划线)在文本上替换为_classname__spam
,其中classname是当前类名,其中前导下划线被剥离。只要它出现在类的定义中,就可以在不考虑标识符的句法位置的情况下完成这种修改。请注意,修改规则主要是为了避免事故;它仍然可以访问或修改被认为是私有的变量。这在特殊情况下甚至可能很有用,例如在调试器中。
请注意,传递给
exec
,eval()
或execfile()
的代码不会将调用类的类名视为当前类;这类似于全局语句的效果,其效果同样限于字节编译在一起的代码。同样的限制适用于getattr()
,setattr()
和delattr()
,以及直接引用__dict__
时。
答案 1 :(得分:1)
我不确定为什么会发生这种情况,但是如果你使用_x
而不是__x
,它就可以正常运行。