【问题标题】:How python resolves private(double underscore) methods inside a class?python如何解析类中的私有(双下划线)方法?
【发布时间】:2019-06-23 19:09:26
【问题描述】:

考虑下面的类

class Foo(object):

    @staticmethod
    def __is():
        print('__is')

    def m(self):
        Foo.__is()  # executes


Foo.__is()  # fails because of mangling

print(Foo.__dict__.keys())

Foo.__is() 在定义类后运行时,由于名称错误而失败。 python解释器如何在方法内部解析Foo.__is()而不在类外部解析?

【问题讨论】:

  • @BernhardVallant 不是重复的 - op 清楚地知道名称修改机制,问题是“这是如何实现的”。
  • 请注意,您的前两个类语句会引发错误,因为 Foo 尚未定义。在它们工作的方法内部使用,因为方法主体在调用之前不会执行。到那时这个类已经定义好了。

标签: python cpython python-internals private-methods


【解决方案1】:

您可以将类视为带有一些口哨声的命名空间。

口哨之一是能够在没有_class__method 的情况下在自己内部解析__methods。这与自动将实例作为第一个参数传递给方法的“魔术”没有什么不同(您的常规 self

为了说明“命名空间”的想法,你可以做一些奇怪的事情,比如

class A:
    def insane():
        return 42

    for _ in range(5):
        print(insane()

【讨论】:

  • 这如何回答这个问题? OP 已经知道您发布的内容,问题是“它实际上是如何实现的”。
【解决方案2】:

类中以__ 开头的名称的名称重整是通过仅在类内将此名称重写为重整形式来实现的。所以你在类中的Foo.__is_Foo__is 替换,它现在存在于类__dict__ 中。该属性可以在类内部或外部访问,因此没有私有保护。但是替换后__is 名称在任何地方都不存在(我认为),这就是为什么它不能从外部工作。

来自 Python 帮助:

“__*” 类私有名称。此类别中的名称,当在 类定义的上下文,被重写以使用损坏的形式 以帮助避免 base 的“私有”属性和 派生类。请参阅标识符(名称)部分。

另请参阅我对您的代码 sn-p 中的错误的评论。

【讨论】:

  • 你是对的。我正在使用 ipython 测试代码,并且类主体内的 Foo.__is() 正在工作,因为它使用的是以前的 Foo 类而不是当前类。
猜你喜欢
  • 2013-01-14
  • 2016-12-03
  • 1970-01-01
  • 1970-01-01
  • 2018-06-30
  • 2011-10-19
  • 2021-11-28
相关资源
最近更新 更多