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

时间:2013-06-24 06:31:57

标签: python multiple-inheritance superclass super method-resolution-order

我一直在尝试理解多重继承环境中super()的行为。我很困惑为什么在test2.py的父类中调用super()导致为父母调用__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__

产生

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

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__

产生

$ ./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'>)

1 个答案:

答案 0 :(得分:6)

你的错误出现在你的评论中:

super(C, self).__init__()  <-- call to object.__init__()

这不是对object.__init__的调用。将类C和实例self都传递给super的原因是它知道接下来要调用什么,而不仅仅是基于类的超类,而是基于MRO的类。实例。基本上,super(C, self).__init__的意思是“在自己的MRO中C之后调用类的__init__”。

这是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__,然后在继承树的路上打印其他消息。)