首先,让我引用一篇来自“专家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
最后,这里是对这里发生的事情的解释:
这是由于A .__ init __(self)调用发生的,这是使用C实例进行的, 从而使super(A,self).__ init __()调用B的构造函数。换句话说, super应该用于整个类层次结构。问题是有时候 此层次结构的一部分位于第三方代码中。
我不知道为什么“super(A, self).__init__()
调用B的构造函数”。请解释这一刻。非常感谢。
答案 0 :(得分:9)
要理解此行为,您必须了解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"
你得到了
MRO: ['C', 'A', 'B', 'object']
C1
A
B
C2
B
C3
显示A
的构造函数如何调用B
。
答案 1 :(得分:4)
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)
在这种情况下,A
会调用B
和Z
。 B
也会调用Z
。