【问题标题】:Python double underscore manglingPython双下划线修饰
【发布时间】:2012-11-09 23:49:38
【问题描述】:

我对这种行为有点困惑(使用 python 3.2):

class Bar:
    pass

bar = Bar()
bar.__cache = None
print(vars(bar))        # {'__cache': None}

class Foo:
    def __init__(self):
        self.__cache = None

foo = Foo()
print(vars(foo))        # {'_Foo__cache': None}

我已经阅读了一些关于双下划线如何导致属性名称“错位”的内容,但我预计在上述两种情况下都会出现相同的名称错位。

What is the meaning of a single- and a double-underscore before an object name?

有什么想法吗?

【问题讨论】:

  • 修改的目的正是为了防止您的第二种情况正常工作。目的是对外部代码隐藏属性。

标签: python attributes python-3.x private-methods double-underscore


【解决方案1】:

在评估class 语句期间会发生名称修改。对于Bar__cache 属性没有定义为类的一部分,而是在事后添加到特定对象中。

(实际上,这可能并不完全正确。在评估 __new__ 方法期间可能会发生名称修改;我不知道。但无论如何,您的 __cache 被显式添加到单个对象中,而不是由类代码。)

【讨论】:

  • 它在编译过程中被破坏了。您可以使用dis.dis() 函数来查看此内容,只需运行import dis; dis.dis(Foo.__init__) 即可查看名称已被破坏。
【解决方案2】:

来自docs

私有名称修改:当一个标识符以文本形式出现在 类定义 以两个或多个下划线字符开头,并且 不以两个或多个下划线结尾,它被认为是私有的 该类的名称。私人名称转换为更长的形式 在为他们生成代码之前。转换插入 名称前面的类名,去掉前导下划线,和 在类名前面插入一个下划线。例如, 出现在名为 Ham 的类中的标识符 __spam 将是 转换为_Ham__spam。这种转变独立于 使用标识符的语法上下文。如果 转换后的名称非常长(超过 255 个字符), 实现定义的截断可能会发生。如果类名 仅由下划线组成,不进行任何转换。

你是在定义类之后分配你的属性

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-28
    • 2016-12-03
    • 1970-01-01
    • 1970-01-01
    • 2012-03-24
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    相关资源
    最近更新 更多