首先,让我引用一篇来自"专家Python编程"一书的文章:
在下面的示例中,使用__init__方法调用其基类的C类将使B类被调用两次!
class A(object):
def __init__(self):
print "A"
super(A, self).__init__()
class B(object):
def __init__(self):
print "B"
super(B, self).__init__()
class C(A,B):
def __init__(self):
print "C"
A.__init__(self)
B.__init__(self)
print "MRO:", [x.__name__ for x in C.__mro__] #prints MRO: ['C', 'A', 'B', 'object']
C() #prints C A B B
Run Code Online (Sandbox Code Playgroud)
最后,这里是对这里发生的事情的解释:
这是由于A .__ init __(self)调用,它是由C实例进行的,因此使super(A,self).__ init __()调用B的构造函数.换句话说,super应该用于整个类层次结构.问题是有时这个层次结构的一部分位于第三方代码中.
我不知道为什么" super(A, self).__init__()调用B的构造函数".请解释这一刻.非常感谢.
要理解这种行为,您必须了解super调用不是基类,而是按顺序搜索下一个匹配方法__mro__.因此,呼叫super(A, self).__init__()着眼于__mro__ == ['C', 'A', 'B', 'object'],认为B与匹配方法中的下一类和调用的方法(构造函数)B.
如果你C改为
class C(A,B):
def __init__(self):
print "C1"
A.__init__(self)
print "C2"
B.__init__(self)
print "C3"
Run Code Online (Sandbox Code Playgroud)
你得到
MRO: ['C', 'A', 'B', 'object']
C1
A
B
C2
B
C3
Run Code Online (Sandbox Code Playgroud)
其中显示了A调用的构造函数B.
的文档super说:
返回一个代理对象,该对象将方法调用委托给该类型的父类或同级类。这对于访问类中已重写的继承方法很有用。搜索顺序与 getattr() 使用的顺序相同,只是跳过类型本身。
当您A.__init__(self)从内部执行时C,将super(A, self)返回<super: <class 'A'>, <C object>>. 由于实例是C( <C object>),C 继承层次结构中的所有类都会被选取。并且__init__向他们所有人发出了呼吁。因此,您会看到“B”被调用两次。
要验证这一点,请添加另一个类“Z”,并让“C”也继承自“Z”。走着瞧吧。
class Z(object):
def __init__(self):
print "Z"
super(Z, self).__init__()
class C(A, B, Z):
def __init__(self):
print "C"
A.__init__(self)
B.__init__(self)
Z.__init__(self)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,A 将调用B和Z。也会B打电话。Z