Python 多重继承中意外的方法调用顺序

问题描述 投票:0回答:1

我有一个名为

USA
的子类,它有两个父类
A
B
父级都有一个名为
change_to_4
的方法,在 B init 中我调用该方法,但没有使用我在 A 中定义的 b 方法,它使用
change_to_4
方法的 A 定义

class A:
    def __init__(self) -> None:
        self.a = 1
        super().__init__()

    def change_to_4(self):
        self.x = 4


class B:
    def __init__(self) -> None:
        self.b = 2
        self.change_to_4()
        super().__init__()

    def change_to_4(self):
        self.b = 4


class USA(A, B):
    def __init__(self) -> None:
        super().__init__()


print(f"A vars = {vars(A())}")
print(f"B vars = {vars(B())}")
print(f"USA vars = {vars(USA())}")

print(f"USA mro -> {USA.__mro__}")

我期待这样的事情

A vars = {'a': 1}
B vars = {'b': 4}
USA vars = {'a': 1, 'b': 4}
USA mro -> (<class '__main__.USA'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)

但是输出是

A vars = {'a': 1}
B vars = {'b': 4}
USA vars = {'a': 1, 'b': 2, 'x': 4}
USA mro -> (<class '__main__.USA'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
python-3.x multiple-inheritance
1个回答
0
投票

当解释器尝试查找实例的属性时,在本例中是在

self.change_to_4
的实例上查找
USA
,它首先尝试在
'change_to_4'
中查找
self.__dict__
,但未能在那里找到它,解释器然后按照
USA
的方法解析顺序(
USA
A
B
object
,如输出所示)在定义了它的第一个基本案例类中查找
change_to_4
属性。

摘自自定义类的文档:

类属性引用在此被转换为查找 字典,例如,

C.x
被翻译为
C.__dict__["x"]
(尽管有 有许多挂钩,可以使用其他方式进行定位 属性)。当在那里找不到属性名称时,该属性 搜索在基类中继续。基类的搜索 使用 C3 方法解析顺序,即使在 存在“钻石”继承结构 通往共同祖先的多重继承路径。

所以在这种情况下,

A
是定义
USA
change_to_4
的第一个基类,因此
self.change_to_4()
被转换为
A.change_to_4(self)
,导致
self.x = 4
被执行。

© www.soinside.com 2019 - 2024. All rights reserved.