Sek*_*mer 5 python inheritance multiple-inheritance diamond-problem
关于python中菱形继承的问题:
A
/ \
B C
\ /
D
Run Code Online (Sandbox Code Playgroud)
我首先创建了这个
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()
Run Code Online (Sandbox Code Playgroud)
它的输出是 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()
Run Code Online (Sandbox Code Playgroud)
输出为 d、b、c、a
有人可以解释为什么该程序会这样运行吗?
为了理解super()我们必须了解 MRO 概念。
MRO 或方法解决顺序
当调用子方法时,应该有一些内部机制来确定调用哪个方法。
MRO 定义了搜索基类以执行方法的顺序。
正在查找方法:
MRO 允许将继承图转换为线性列表以进行迭代。
代码中发生了什么
在此版本中,D定义了类:
class D(B,C):
def __init__(self):
print('d')
super().__init__()
Run Code Online (Sandbox Code Playgroud)
因此,当D对象被创建时,我们看到“d”作为第一个输入。
然后在D构造函数中调用:
super().__init__()
Run Code Online (Sandbox Code Playgroud)
该super()方法调用 MRO 中的下一个类。
D维护、维修和运营是:
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
print(D.__mro__)
Run Code Online (Sandbox Code Playgroud)
B因此,下一个类的B构造函数已被调用,我们见证了B第二个输出。
类B构造函数是:
class B(A):
def __init__(self):
print('b')
A.__init__(self)
Run Code Online (Sandbox Code Playgroud)
因此它直接调用 A 类构造函数,我们看到“A”是第三个也是最后一个输出。
在此版本中,类D构造函数与以前相同,因此第一个输出再次为“d”。
然后,像之前一样B调用构造函数,并打印“b”作为第二个输出:
class B(A):
def __init__(self):
print('b')
super().__init__()
Run Code Online (Sandbox Code Playgroud)
然而,这一次,super()又被召唤了。
在查看DMRO时(注意我们是构造函数D中的对象B,所以相关的MRO是 of D):
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
Run Code Online (Sandbox Code Playgroud)
下一个类是C,因此C正在调用构造函数,我们见证“c”作为第三个输出:
class C(A):
def __init__(self):
print('c')
super().__init__()
Run Code Online (Sandbox Code Playgroud)
最后,super()再次调用该方法,并在 MRO 之后我们以 class 结束A:
class A:
def __init__(self):
print('a')
Run Code Online (Sandbox Code Playgroud)
最后的输出是'a',我们就完成了。
更多关于
阅读super()文档中有关方法的更多信息。