属性名称与父类名称在第一次解析时而不是子类名称在实例化/调用时混合在一起

问题描述

在尝试测试某些代码时,我尝试访问子类(__var)的名称混杂属性时遇到了一些意外行为。没得到孩子的价值,我以为我得到了父类的__var。

最终编辑:子对象访问其自身的变量版本,该名称与父对象的名称(而不是其自身的名称)成对。现在可以了解以前的意外行为。

class test_parent(object):
    __var = 1

    def getvar(self):
        a = self.__class__.__var
        return a

class test_child(test_parent):
    __var = 2

a = test_parent()
b = test_child()
b.__class__._test_parent__var = 3

print(a.getvar())                       # Prints 1,as expected
print(b.__class__._test_child__var)     # Prints 2,as expected
print(b.__class__._test_parent__var)    # Prints 3,as expected
print(b.getvar())                       # Prints 3

解决方法

在评论中得到了帮助:

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

首次遇到__var时,它位于test_parent的主体内,并且被名称拼凑:

class test_parent(object):
    __var = 1

成为:

class test_parent(object):
    _test_parent__var = 1

__var中遇到test_child成为_test_child__var时,也会发生类似的情况。之所以发生先前的意外行为,是因为同一件事发生在getvar内部。

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

成为:

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

这就是为什么一旦将b.getvar()分配给测试代码3就会返回b.__class__._test_parent__var的原因,因为那是getvar方法访问的值。