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

问题描述:

下面的代码:为什么__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

双下划线调用名称修改。如果你不需要名字改编,不要使用双undescore

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是当前类名称,前导下划线已剥离。只要它在类的定义内发生,就不会考虑标识符的语法位置。

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

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

+0

糟糕,我错过了'__y'的下划线。我现在纠正了它。仍然存在不对称,但我认为你已经遇到了核心问题。 – Draemon 2010-03-05 12:01:35

我不知道到底为什么发生这种情况,但如果你使用_x而不是__x它的作品如你所愿。

+0

它被称为名称修改:http://docs.python.org/tutorial/classes.html#private-variables – SilentGhost 2010-03-05 11:58:32

+0

确实。有趣的是'__x__'没有得名。 – 2010-03-05 12:04:00

+0

@ar,'__x__'还有另一个特殊的含义 – 2010-03-05 12:05:28