为什么所有双下划线变量都在类方法中被混用

时间:2019-06-21 00:09:42

标签: python

编辑:当前的两个答案都讨论了类内部存在混乱的事实。我的问题是关于类方法内部的值-请注意,方法范围内的解析与类范围不同,否则test_json_lifetime()将是可打印的。


在python 2.7和3.6中似乎是这种情况。

例如,此代码

__CLASS

会给予

__GLOBAL = 'global'
_Bar__MANGLED_GLOBAL = 'mangled global'

class Bar(object):
    __CLASS = 'class'

    def baz(self):
        __LOCAL = 'local'
        try:
            print __LOCAL
        except Exception as e:
            print e
        try:
            print __CLASS
        except Exception as e:
            print e
        try:
            print __GLOBAL
        except Exception as e:
            print e
        try:
            print __MANGLED_GLOBAL
        except Exception as e:
            print e

Bar().baz()

当存在local global name '_Bar__CLASS' is not defined global name '_Bar__GLOBAL' is not defined mangled global 或需要类级别的other.__x等于__foo时,我理解逻辑,但这似乎是一种疏忽,其中类范围内的任何内容被自动重写。

2 个答案:

答案 0 :(得分:2)

更新:起初,我并没有真正回答问题,但是根据线索,我终于找到了真正的答案,因此请耐心阅读直到最后。 简而言之,修饰是针对班级中出现的所有名称。

Python类不能具有真正的私有属性,前缀__用于private

我看到了以下建议:

  

但是请避免使用__private表格。我从不使用它。相信我。如果您使用它,则以后后悔。

和:

  

表单__private仅触发一个private name mangling,其目的是为了防止子类中的命名空间意外碰撞:MyClass.__private仅变成MyClass._MyClass__private

Code Like a Pythonista: Idiomatic Python-naming

我看了private name mangling,并据此认为是对班上所有names的改造:

  

私人名称处理::当在类定义中以文本形式出现的标识符以两个或多个下划线字符开头,而不以两个或多个下划线结尾时,被视为该课程的 私有名称

因此,似乎对类中出现的所有名称都进行了整形,这就是为什么所有双下划线变量都在类方法中进行整形的原因。

答案 1 :(得分:2)

这不是疏忽。实际上,私有全局变量曾经在tutorial中专门投放广告:

  

现在对类专用标识符的支持有限。格式为__spam的任何标识符(至少两个前导下划线,至多一个尾随下划线)现在在文本上被替换为_classname__spam,其中classname是当前类名,前导下划线)剥离。进行这种处理时无需考虑标识符的语法位置,因此可用于定义类私有实例和类变量,方法,以及全局变量,甚至可以存储私有实例变量 other 类的实例访问该类。

如果没有特定的参考,例如邮件列表对话之类的内容,我们只能推测为什么以这种方式设计。 (我检查了提交历史,但是original commit不包含设计选择的依据。)我们可以推测这是为了启用私有全局变量之类的东西,但我们也可以推测这是最容易实现的方式而且如果其他选择更容易的话,实施者也不会被私有全球企业的前景所左右。以仅影响类的实例和类属性的方式实现名称修饰肯定会困难得多。