为什么__setattr__的“name”参数包含该类,但__getattr__不包含该类?

时间:2010-03-05 11:47:39

标签: python setattr 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

2 个答案:

答案 0 :(得分:4)

双下划线调用名称重整。如果您不需要名称修改,请不要使用双重非意外

What is the meaning of a single- and a double-underscore before an object name?

来自Python docs

  

9.6。私人变量

     

在Python中不存在除了从对象内部访问之外无法访问的“私有”实例变量。但是,大多数Python代码都遵循一个约定:前缀为下划线的名称(例如_spam)应被视为API的非公共部分(无论是函数,方法还是数据成员)。它应被视为实施细节,如有更改,恕不另行通知。

     

由于类私有成员有一个有效的用例(即为了避免名称与子类定义的名称冲突),对这种称为名称修改的机制的支持有限。表单__spam的任何标识符(至少两个前导下划线,最多一个尾随下划线)在文本上替换为_classname__spam,其中classname是当前类名,其中前导下划线被剥离。只要它出现在类的定义中,就可以在不考虑标识符的句法位置的情况下完成这种修改。

     

请注意,修改规则主要是为了避免事故;它仍然可以访问或修改被认为是私有的变量。这在特殊情况下甚至可能很有用,例如在调试器中。

     

请注意,传递给execeval()execfile()的代码不会将调用类的类名视为当前类;这类似于全局语句的效果,其效果同样限于字节编译在一起的代码。同样的限制适用于getattr()setattr()delattr(),以及直接引用__dict__时。

答案 1 :(得分:1)

我不确定为什么会发生这种情况,但是如果你使用_x而不是__x,它就可以正常运行。