为什么 python 在这里处理

Why is python mangling here

如果没有 cls,为什么这段代码会失败。在 __TEXT

之前
__TEXT = "abcde"

print(__TEXT)
class aaa():
    @classmethod
    def bbb(cls):
        print(__TEXT)

aaa.bbb()

输出为:

abcde
Traceback (most recent call last):
  File "<string>", line 9, in <module>
  File "<string>", line 7, in bbb
NameError: name '_aaa__TEXT' is not defined

如果您将 __TEXT 设为 class 变量并尝试在不使用 class 前缀的情况下引用它,如下所示:

class aaa():
    __TEXT = "abcde"
    @classmethod
    def bbb(cls):
        print(cls.__TEXT)
        print(__TEXT)

x = aaa()
x.bbb()

你得到同样的错误,但它没有意义:

abcde
Traceback (most recent call last):
  File "<string>", line 10, in <module>
  File "<string>", line 7, in bbb
NameError: name '_aaa__TEXT' is not defined

不太确定这是否是错误,但您可以让该函数需要一个参数文本,这似乎工作得很好。不过您需要提供更多信息,以便我尽力提供帮助。

    __TEXT = "abcde"

    print(__TEXT)
    class aaa():
    @classmethod
    def bbb(self, __TEXT):
       print(__TEXT)

    aaa.bbb(__TEXT)

双下划线前缀导致 Python 解释器重写属性名称以避免子classes 中的命名冲突。

这也称为“名称修改”。解释器更改变量名称的方式使得在 class 稍后扩展时更难产生冲突。

参考文档:https://docs.python.org/3/tutorial/classes.html#private-variables

PEP 8中,他们明确表示:

__double_leading_underscore: when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo ...).

注意以粗体显示的选择。在他们提请注意 mangling 在命名 class 属性时使用的完全相同的句子中,他们指出 mangling 发生在 classany __boo 内部=],这完美地解释了您正在观察的内容。

Python 解释器 mangles variable-names 与 double-underscore 避免 名称与子类 .

定义的 variable-names 冲突

这背后的目标几乎等同于 Java 中的最终变量和 C++ 中的非虚拟变量。

举个例子:

class Human:
    def __init__(self):
        self.surname = 'Jeffrey'
        self._age = 22
        self.__id = 5

# Let's check the variables associated with this class
x = Human()
print(dir(x)) # gives: ['_Human__id', ..., '_age', 'name']

# Create a subclass 'Cook'

class Cook(Human):
    def __init__(self):
        Human.__init__(self)        
        self.__id = 25

y = Cook()
print(dir(y)) # gives: ['_Human__id', '_Cook__id', ..., '_age', 'name']