2

以下代码:

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
4

2 回答 2

5

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

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

来自Python 文档

9.6。私有变量

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

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

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

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

于 2010-03-05T11:52:46.483 回答
1

我不确定为什么会发生这种情况,但是如果您使用它_x而不是__x按预期工作。

于 2010-03-05T11:55:33.337 回答