python私有属性名mangling inheritan

2024-06-11 03:51:24 发布

您现在位置:Python中文网/ 问答频道 /正文

这是“有效Python”中的一个例子,我显然遗漏了一些东西。我加了一些指纹来帮助说服自己,但我还是有点不清楚。在

我知道当您尝试访问继承的私有变量时,它会失败,因为在子实例字典中,名称已损坏(下面最后一行,尝试正确访问a.__value失败,因为实例dict包含损坏的版本_ApiClass__value)。在

我遇到的问题是继承的方法get没有这个问题。如果您在对get的调用中打印self.__dict__,您可以看到我们仍在使用相同的子实例dict,就像我们试图直接从子实例dict使用点式访问一样(它只包含损坏的名称)。从这个方法中的点式属性访问以某种方式正确地转换为损坏的名称并检索私有变量。在

我对属性访问的理解是,在本质上发生的事情(尽管简化了)是a.__value基本上是{}。当您尝试直接访问继承的私有变量时,这是有意义的,因为它失败了,因为只有损坏的名称在子dict中。但是,继承的方法get(它在同一实例dict from Child上操作)与点式访问一起工作,因此它显然没有执行a.__dict__['__value'],而是a.__dict__['_ApiClass__value']。在

这里的区别是什么使来自get方法中的私有属性访问知道损坏的名称,而不是从子级访问类似的属性?在

class ApiClass():
    def __init__(self):
        self.__value = 5

    def get(self):
        print(self.__dict__['_ApiClass__value']) #succeeds
        print(self.__dict['__value']) #fails bc name mangle
        return self.__value #how is this translated to '_ApiClass_value'
                            #but a similar instance lookup fails?

class Child(ApiClass):
    def __init__(self):
        super().__init__()
        self._value = 'hello'

a = Child()
print(a.__dict__)
print(a.get())   #works, but instance dict has no '__value' key? 
print(a.__value) #fail bc name mangled to '_ApiClass_value'

Tags: 实例方法self名称childget属性init
1条回答
网友
1楼 · 发布于 2024-06-11 03:51:24

名称混乱是在字节码编译时完成的,因此名称混乱取决于函数的定义位置,而不是函数的调用方式。Child没有自己的get方法,它使用的是ApiClass,而{}的{}被损坏以使用{}。在

这是故意的。这里的目标是使在类X中定义的方法为X而损坏,无论您如何到达它们。如果它们没有,并且父变量和子变量都定义了一个同名的私有变量,那么父变量就不能私有访问它自己唯一的变量版本,它将与子变量共享(即使变量的含义在每种情况下可能完全不同)。在

dis模块可以演示在编译时进行损坏的事实:

class Parent:
    def x(self):
        return self.__x

class Child(Parent):
    pass

然后交互检查:

^{pr2}$

注意,LOAD_ATTR值,_Parent__x是硬编码到字节码中的。在

您还可以演示普通函数(与定义为类的一部分的方法不同)中如何不涉及特殊行为:

>>> def foo(bar): return bar.__x
>>> dis.dis(foo)
  1           0 LOAD_FAST                0 (bar)
              3 LOAD_ATTR                0 (__x)
              6 RETURN_VALUE

如果LOAD_ATTR只是试图加载普通的__x名称,而不是损坏的版本;如果bar是一个类的实例,那么由于名称损坏保护,这是非常不可能的。在

相关问题 更多 >