为什么“名称"如此__setattr__的参数包括该类,但是__getattr__不呢? [英] Why does the "name" parameter to __setattr__ include the class, but __getattr__ doesn't?

查看:111
本文介绍了为什么“名称"如此__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

文档完全无济于事,指出名称"是属性名称",但是由于某些原因,根据您是设置还是获取它而有所不同.

The documentation is utterly unhelpful stating the "name" is the "name of the attribute", yet for some reason it's different depending on whether you are setting it or getting it.

我想知道的是:

  • 我在这里做错了什么吗?
  • 在第一种情况下如何获取x而不是_MyClass__x?
  • Am I doing something fundamentally wrong here?
  • How do I get x in the first case instead of _MyClass__x?

推荐答案

双下划线调用名称修饰.如果您不需要名称修饰,请不要使用double undescore

The double underscore invokes name mangling. If you don't need name mangling, don't use double undescore

在对象名称前加一个单下划线和双下划线是什么意思?

Python文档

9.6.私有变量

只能从对象内部访问的私有"实例变量在Python中不存在.但是,大多数Python代码遵循一个约定:以下划线开头的名称(例如_spam)应被视为API的非公开部分(无论是函数,方法还是数据)成员).应该将其视为实现细节,并且如有更改,恕不另行通知.

9.6. Private Variables

"Private" instance variables that cannot be accessed except from inside an object, don’t exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice.

由于类私有成员有一个有效的用例(即避免名称与子类定义的名称发生名称冲突),因此对这种称为名称处理的机制的支持有限.任何形式为__spam的标识符(至少两个前导下划线,最多一个尾随下划线)在文本上均被_classname__spam替换,其中classname是当前类名,其中前导下划线被去除.只要不存在标识符的语法位置,就可以进行这种修饰,只要它出现在类的定义之内即可.

Since there is a valid use-case for class-private members (namely to avoid name clashes of names with names defined by subclasses), there is limited support for such a mechanism, called name mangling. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.

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

Note that the mangling rules are designed mostly to avoid accidents; it still is possible to access or modify a variable that is considered private. This can even be useful in special circumstances, such as in the debugger.

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

Notice that code passed to exec, eval() or execfile() does not consider the classname of the invoking class to be the current class; this is similar to the effect of the global statement, the effect of which is likewise restricted to code that is byte-compiled together. The same restriction applies to getattr(), setattr() and delattr(), as well as when referencing __dict__ directly.

这篇关于为什么“名称"如此__setattr__的参数包括该类,但是__getattr__不呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆