Python 属性名称与父类名称(在第一次解析时)而不是子类名称(在实例化/调用时)冲突

Python 属性名称与父类名称(在第一次解析时)而不是子类名称(在实例化/调用时)冲突,python,inheritance,name-mangling,Python,Inheritance,Name Mangling,在测试某些代码时,我遇到了一些意外的行为,当时我试图访问子类(_var)的name-mangled属性。我以为我得到的不是子类的值,而是父类的_变量 最终编辑:子对象访问自己版本的变量,该变量的名称被父对象的名称而不是自己的名称弄乱。以前意想不到的行为现在已经被理解了 类测试\u父对象(对象): __var=1 def getvar(self): a=自类变量 归还 类测试子级(测试父级): __var=2 a=测试父项() b=测试子项() b、 _uuuuuuuuuuuuuuuuuuuu类u

在测试某些代码时,我遇到了一些意外的行为,当时我试图访问子类(_var)的name-mangled属性。我以为我得到的不是子类的值,而是父类的_变量

最终编辑:子对象访问自己版本的变量,该变量的名称被父对象的名称而不是自己的名称弄乱。以前意想不到的行为现在已经被理解了

类测试\u父对象(对象):
__var=1
def getvar(self):
a=自类变量
归还
类测试子级(测试父级):
__var=2
a=测试父项()
b=测试子项()
b、 _uuuuuuuuuuuuuuuuuuuu类uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
打印(a.getvar())#按预期打印1
打印(b.uuu类uuu.测试u子项uuu变量)#按预期打印2张
打印(b.uuu类uuu.u测试u父项uuu变量)#按预期打印3个
打印(b.getvar())#打印3

通过以下评论的帮助回答:

当解释器“读取”该方法时(可能不是正确的术语),而不是调用该方法时,就会出现Python名称混乱。测试证明了在后台发生的过程

第一次遇到_var时,它位于test_parent的主体内,并且名称已损坏:

class test_parent(object):
    __var = 1
变成:

class test_parent(object):
    _test_parent__var = 1
class test_parent(object):
    ...
    def getvar(self):
        ...
        a = self.__class__._test__parent_var
类似的情况发生在
\uuuvar
测试\uchild
中遇到
\utest\uchild\uvar
时。发生之前意外的行为是因为在getvar中发生了同样的事情

class test_parent(object):
    ...
    def getvar(self):
        ...
        a = self.__class__.__var
变成:

class test_parent(object):
    _test_parent__var = 1
class test_parent(object):
    ...
    def getvar(self):
        ...
        a = self.__class__._test__parent_var

这就是为什么测试代码
b.getvar()
返回
3
一次
b.\uuuu class\uuuu.\uu test\u parent\uuu var
被分配给它,因为这是getvar方法访问的值。

如果发生了您预期的情况,它将无法实现名称篡改的全部目的。弄虚作假的全部目的是为了避免这种情况发生。否则,您只需使用常规属性名称。名称混乱的关键是确保当超类和子类都希望使用名称
\uu var
时,这些使用彼此无关,并且不会相互影响。让子类
\uu var
影响超类代码将无法达到此目的。@jrmylow,因为这是名称混乱的全部目的。这是为了防止子类中的名称冲突。如果你不想这种行为,请不要使用双下划线名称,因为这也是它的全部目的。
self.\uu var
将引用
中的
\uuu var
,它是在
中按词汇定义的。它不关心
self
的类型,也不关心它与继承的关系。@geckos不,self的身份是不相关的,当您调用
child\u实例时。getvar()
self
实际上是一个
child
实例。重要的是方法是在父类还是子类*中定义的。不管
self
是什么,因为同样,
self
将对应于实例