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

Dra*_*mon 3 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
Run Code Online (Sandbox Code Playgroud)

输出:

_MyClass__x
__y
Traceback (most recent call last):
...
AttributeError: __y
Run Code Online (Sandbox Code Playgroud)

该文档完全没有帮助说明“名称”是“属性的名称”,但由于某种原因,它会有所不同,具体取决于您是设置它还是获取它。

我想知道的是:

  • 我在这里做的是根本错误的事情吗?
  • 我如何进入x第一种情况而不是_MyClass__x

Joh*_*ooy 6

双下划线调用名称修改。如果您不需要名称修饰,请不要使用双取消划线

\n\n

对象名称前的单下划线和双下划线的含义是什么?

\n\n

来自Python 文档

\n\n
\n

9.6。私有变量

\n\n

\xe2\x80\x9cPrivate\xe2\x80\x9d 实例变量只能从对象内部访问,Python 中不存在 \xe2\x80\x99t 。然而,大多数 Python 代码都遵循一个约定:以下划线前缀的名称(例如_spam)应被视为 API 的非公共部分(无论是函数、方法还是数据成员)。它应被视为实施细节,如有更改,恕不另行通知。

\n\n

由于类私有成员有一个有效的用例(即避免名称与子类定义的名称发生名称冲突),因此对这种称为名称修饰的机制的支持有限。该形式的任何标识符__spam(至少两个前导下划线,最多一个尾随下划线)在文本上都替换为_classname__spam,其中 classname 是删除了前导下划线的当前类名称。这种修改的完成与标识符的语法位置无关,只要它出现在类的定义中即可。

\n\n

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

\n\n

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

\n
\n