为什么 __setattr__ 的“name”参数包含该类,而 __getattr__ 不包含该类?
题
下面的代码:
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
?
解决方案
双下划线调用名称修改。如果不需要名称修饰,请不要使用双取消划线
来自 Python 文档
9.6。私有变量
Python 中不存在只能从对象内部访问的“私有”实例变量。然而,大多数 Python 代码都遵循一个约定:带有下划线前缀的名称(例如
_spam
)应被视为 API 的非公共部分(无论是函数、方法还是数据成员)。它应被视为实施细节,如有更改,恕不另行通知。由于类私有成员有一个有效的用例(即避免名称与子类定义的名称发生名称冲突),因此对这种称为名称修饰的机制的支持有限。任何形式的标识符
__spam
(至少两个前导下划线,最多一个尾随下划线)在文本上替换为_classname__spam
, ,其中 classname 是当前类名,去掉了前导下划线。这种修改的完成与标识符的语法位置无关,只要它出现在类的定义中即可。请注意,损坏规则主要是为了避免事故而设计的;仍然可以访问或修改被视为私有的变量。这甚至在特殊情况下很有用,例如在调试器中。
请注意,代码传递到
exec
,eval()
或者execfile()
不认为调用类的类名是当前类;这类似于全局语句的效果,其效果同样仅限于字节编译在一起的代码。同样的限制适用于getattr()
,setattr()
和delattr()
, ,以及引用时__dict__
直接地。
其他提示
我不确定为什么会发生这种情况,但是如果您使用 _x
而不是 __x
它可以按照您的期望工作。
不隶属于 StackOverflow