Python 中的钻石继承

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

关于python中菱形继承的问题:

  A
/   \
B    C
\   /
  D

我首先创建了这个

class A:
    def __init__(self):
        print('a')

class B(A):
    def __init__(self):
        print('b')
        A.__init__(self)

class C(A):
    def __init__(self):
        print('c')
        A.__init__(self)

class D(B,C):
    def __init__(self):
        print('d')
        super().__init__()

test = D()

它的输出是 d, b, a

更改 B 和 C 后

A.__init__() to super()

class A:
    def __init__(self):
        print('a')

class B(A):
    def __init__(self):
        print('b')
        super().__init__()  # THIS AND ^^

class C(A):
    def __init__(self):
        print('c')
        super().__init__()   # THIS  ^^

class D(B,C):
    def __init__(self):
        print('d')
        super().__init__()

test = D()

输出为d、b、c、a

有人可以解释为什么程序会这样吗?

python inheritance multiple-inheritance diamond-problem
1个回答
6
投票

为了理解

super()
,我们必须理解MRO概念。

MRO 或方法解析顺序

当调用子方法时,应该有一些内部机制来确定调用哪个方法。

MRO,定义搜索基类以执行方法的顺序。

正在寻找方法:

  1. 在子类本身中。
  2. 按照继承中指定的顺序,在DFS中。

MRO 允许将继承图转换为线性列表以进行迭代。

代码中发生了什么

  1. 第一版

在此版本中,定义了类

D

class D(B,C):
    def __init__(self):
        print('d')
        super().__init__()

因此,当创建

D
对象时,我们见证了“d”作为第一个输入。

然后在

D
构造函数中调用:

super().__init__()

super()
方法调用MRO中的下一个类。

D
MRO 是:

# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
print(D.__mro__)

所以下一个类是

B
,因此
B
构造函数被调用,我们见证了
B
作为第二个输出。

B
构造函数是:

class B(A):
    def __init__(self):
        print('b')
        A.__init__(self)

因此它直接调用 A 类构造函数,我们见证“A”作为第三个也是最后一个输出。

  1. 第二版

在此版本中,类

D
构造函数与以前相同,因此第一个输出再次为“d”。

然后,像之前一样,调用构造函数,并打印“b”作为第二个输出:

B

然而,这一次,
class B(A): def __init__(self): print('b') super().__init__()

再次被召唤。

查看

super()

MRO时(注意,我们在

D
构造函数中是
D
对象,所以相关的MRO是
B
):
D

下一个类是
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

,因此正在调用

C
构造函数,我们见证'c'作为第三个输出:
C

最后,
class C(A): def __init__(self): print('c') super().__init__()

方法再次被调用,并且在MRO之后我们以类

super()
结束:
A

最后输出是'a',我们就完成了。

更多关于 阅读文档中有关

class A: def __init__(self): print('a') 方法的更多信息

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