为什么在父类__init __()中调用super()会改变子类__init __()的行为?

cdw*_*son 4 python multiple-inheritance super superclass method-resolution-order

我一直试图理解super()多重继承的上下文中的行为.我很困惑为什么super()在test2.py的父类中调用会导致__init__()为父母双方调用?

test1.py

#!/usr/bin/env python

class A(object):

    def __init__(self):
        self.A = "A"
        print self.A

class B(object):

    def __init__(self):
        self.B = "B"
        print self.B

class C(A, B):

    def __init__(self):
        self.C = "C"
        print self.C
        super(C, self).__init__()

if __name__ == '__main__':
    print "Without super() in parent __init__():"
    c = C()
    print c.__dict__
    print C.__mro__
Run Code Online (Sandbox Code Playgroud)

生产:

$ ./test.py 
Without super() in parent __init__():
C
A
{'A': 'A', 'C': 'C'}
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>)
Run Code Online (Sandbox Code Playgroud)

test2.py

#!/usr/bin/env python

class A(object):

    def __init__(self):
        self.A = "A"
        print self.A
        super(A, self).__init__()

class B(object):

    def __init__(self):
        self.B = "B"
        print self.B
        super(B, self).__init__()

class C(A, B):

    def __init__(self):
        self.C = "C"
        print self.C
        super(C, self).__init__()

if __name__ == '__main__':
    print "With super() in parent __init__():"
    c = C()
    print c.__dict__
    print C.__mro__
Run Code Online (Sandbox Code Playgroud)

生产:

$ ./test2.py 
With super() in parent __init__():
C
A
B
{'A': 'A', 'C': 'C', 'B': 'B'}
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>)
Run Code Online (Sandbox Code Playgroud)

Bre*_*arn 6

你的错误在你的评论中:

super(C, self).__init__()  <-- call to object.__init__()
Run Code Online (Sandbox Code Playgroud)

这不是一个电话object.__init__.将类C和实例都传递selfsuper它的原因是它知道接下来要调用什么,而不仅仅是基于类的超类,而是基于实例的MRO.从本质上讲,super(C, self).__init__意思是" __init__在自己的MRO中C之后调用该类".

这是整个观点super---它允许合作继承,其中一个类可以调用super意味着"传递控制MRO中的下一个类",而无需在类定义时知道哪个类是什么.

所以当你打电话时super(C, self).__init__,那个叫A.__init__,因为A是MRO中C之后的下一个类.然后当A调用super(A, self).__init__时,调用B.__init__,因为B是MRO中A之后的类.

(请注意,您的消息以相反的顺序打印--- B,A,C ---因为您调用超类方法打印每条消息.所以第一条消息在执行完成之前不会被打印出来B.__init__,然后在继承树的回路上打印其他消息.)