请考虑以下情况:
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__
不好,因为跳过了
Cs
__init__。其原因是因为
B的
__init__调用
A的
__init__直接。
的目的super
是解决继承钻石。如果您取消评论
# super(B,self).__init__()
和注释掉
A.__init__(self)
该代码产生了更令人满意的结果:
Running D.__init__Running B.__init__Running C.__init__Running A.__init__
现在,所有
__init__方法都被调用。请注意,在当时你定义
B.__init__你可能会 认为
这
super(B,self).__init__()是与调用
A.__init__(self),但是你错了。在上述情况下,
super(B,self).__init__()实际上调用
C.__init__(self)。
圣烟,
B一无所知
C,却
super(B,self)知道调用
C的
__init__?原因是因为
self.__class__.mro()包含
C。换句话说,
self(或以上所述
foo)了解
C。
所以要小心-两者不可互换。它们可以产生截然不同的结果。
使用
super有陷阱。继承图中的所有类之间需要相当大的协调。(例如,它们必须具有相同的呼叫签名
__init__,因为任何特定的
__init__人都不知道
__init__
super接下来会呼叫另一个,或者使用
**kwargs。)此外,您必须在
super任何地方都保持一致。跳过一次(如上例所示),您将失去的全部目的
super。请参阅链接以了解更多陷阱。
如果您完全控制类的层次结构,或者避免使用继承菱形,则不需要
super。



