Python的super

by jin

2018-11-13

测试程序:

class A(object):

    def __init__(self):
        print ('init A…')
        
class B(A):
    def __init__(self):
        super().__init__()
        print('init B…')
        
class C(A):
    def __init__(self):
        # super().__init__()
        print('init C…')

class D(B, C):
    def __init__(self):
        super().__init__()

print('init D…')

>>> D()

init C…
init B…
init D…

<__main__.D object at 0x0000021D14E99DA0>

为什么?

>>> D.__mro__


          

(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

所以Python的super() == super(Class, self)并不像兄弟语言一样,提供一个父类对象,而是mro列表中的后继类。上述测试中如果取消掉将C.__init__中注释的语句,便能通过super(C,self)寻到类A,打印出 init A…

Python Documentation也证实了这个设计:

The second use case is to support cooperative multiple inheritance in a dynamic execution environment. This use case is unique to Python and is not found in statically compiled languages or languages that only support single inheritance. This makes it possible to implement “diamond diagrams” where multiple base classes implement the same method. Good design dictates that this method have the same calling signature in every case (because the order of calls is determined at runtime, because that order adapts to changes in the class hierarchy, and because that order can include sibling classes that are unknown prior to runtime).

引入这种super语义可解决多继承中的"菱形图"问题。仍以取消注释后的测试程序为例,只要每个函数都调用super()中的同名函数,不仅能保证A的方法只调用一次,而且B,C类中的方法将以一个固定的顺序进行调用。