代码之家  ›  专栏  ›  技术社区  ›  Draemon

为什么setattr的“name”参数包含类,但是getattr不包含?

  •  2
  • Draemon  · 技术社区  · 14 年前

    以下代码:

    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
    

    说明“name”是“name of the attribute”的文档是完全没有帮助的,但是由于某些原因,这取决于您是设置它还是获取它。

    我想知道的是:

    • 我在这里做了什么根本性的错误吗?
    • 我如何得到 x 在第一种情况下 _MyClass__x ?
    2 回复  |  直到 14 年前
        1
  •  4
  •   Community TheSoundDefense    7 年前

    双下划线调用名称损坏。如果你不需要名称损坏,不要使用双不得分

    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 ,其中class name是当前类名,去掉前导下划线。只要它出现在类的定义中,就可以在不考虑标识符的语法位置的情况下进行这种处理。

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

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

        2
  •  1
  •   a'r    14 年前

    我不知道为什么会这样,但是如果你用 _x 而不是 __x 正如你所料。