考虑以下情况:
class A(object):
def __init__(self):
print('Running A.__init__')
super(A,self).__init__()
class B(A):
def __init__(self):
print('Running B.__init__')
# super(B,self).__init__()
A.__init__(self)
class C(A):
def __init__(self):
print('Running C.__init__')
super(C,self).__init__()
class D(B,C):
def __init__(self):
print('Running D.__init__')
super(D,self).__init__()
foo=D()
因此,这些类形成了所谓的继承菱形:
A
/ \
B C
\ /
D
运行代码会得到
Running D.__init__
Running B.__init__
Running A.__init__
这很糟糕,因为C
's __init__
被跳过。这样做的原因是因为B
's __init__
calls A
's __init__
直接地。
的目的super
就是解决继承钻石。如果你取消评论
# super(B,self).__init__()
并注释掉
A.__init__(self)
该代码产生更理想的结果:
Running D.__init__
Running B.__init__
Running C.__init__
Running A.__init__
现在所有的__init__
方法被调用。请注意,在您定义时B.__init__
你可能会think that super(B,self).__init__()
与调用相同A.__init__(self)
,但你错了。在上述情况下,super(B,self).__init__()
实际上打电话C.__init__(self)
.
圣烟,B
一无所知C
, 但是super(B,self)
知道打电话C
's __init__
?原因是因为self.__class__.mro()
包含C
。换句话说,self
(或者在上面,foo
)知道C
.
所以要小心——两者是不可替代的。它们可以产生截然不同的结果。
Using super
有陷阱。继承图中的所有类之间需要相当程度的协调。 (例如,它们必须具有相同的调用签名__init__
,因为任何特定的__init__
不知道还有哪些__init__
super
接下来可能会打电话,或者
别的use **kwargs.) 此外,您必须始终如一地使用super
到处。跳过一次(如上面的例子),你就达不到了super
。
请参阅链接了解更多陷阱。
如果您可以完全控制类层次结构,或者避免继承菱形,那么就不需要super
.