首先来一段单继承中使用 super() 的示例:

class Parent: 
    def __init__(self): 
        print('Parent.__init__()') 


class Son(Parent): 
    def __init__(self): 
        super().__init__()      # 等于 Parent.__init__() 
        print('Son.__init__()') 


son = Son() 

'''
Parent.__init__()
Son.__init__()
'''

这时 super().__init__()Parent.__init__() 是等价的。

下面改一下,如果有多继承,但是没有出现菱形继承的情况:

class Son:
    def __init__(self):
        print('Son.__init__()')


class Daughter:
    def __init__(self):
        print('Daughter.__init__()')


class Grandson(Son, Daughter):
    def __init__(self):
        super(Grandson, self).__init__()     # 等于 super().__init__() 
        super(Son, self).__init__() 
        print('Grandson.__init__()')


print(Grandson.__mro__)
grandson = Grandson() 

'''
(<class '__main__.Grandson'>, <class '__main__.Son'>, <class '__main__.Daughter'>, <class 'object'>)
Son.__init__()
Daughter.__init__()
Grandson.__init__()
'''

这里的 __mro__ 是什么?MRO 全称是 Method Resolution Order ,也就是方法解析顺序,主要用于多继承时判断调用的属性来自哪个类。从上面的输出可以看到,调用 Grandson 中的类时,解析的顺序是 Grandson, Son, Daughter

super() 是什么?使用 super() 可以确保我们调用父类的构造函数。内部使用 C3 算法,这个之后再说。

还是上面那种继承关系,我们可不可以用下面这种写法:

Son.__init__()
Daughter.__init__()

是可以的,分别调用了 SonDaughter 的构造方法。

下面再改一下,如果是存在菱形继承的多继承呢?

class Parent:
    def __init__(self):
        print('Parent.__init__()')


class Son(Parent):
    def __init__(self):
        super(Son, self).__init__()
        print('Son.__init__()')


class Daughter(Parent):
    def __init__(self):
        super(Daughter, self).__init__()
        print('Daughter.__init__()')


class Grandson(Son, Daughter):
    def __init__(self):
        super(Grandson, self).__init__()
        super(Son, self).__init__()
        print('Grandson.__init__()')


print(Grandson.__mro__)
grandson = Grandson()

'''
(<class '__main__.Grandson'>, <class '__main__.Son'>, <class '__main__.Daughter'>, <class '__main__.Parent'>, <class 'object'>)
Parent.__init__()
Daughter.__init__()
Son.__init__()
Parent.__init__()
Daughter.__init__()
Grandson.__init__()
'''

结果显示调用了两次 Parent 的构造函数。显然是不需要的,如何解决?使用 类名.__init__() 的形式可以吗?

不可以,你可以自己试试,结果还是一样的。

解决方法是把 Grandsonsuper(Son, self).__init__() 这条语句删掉即可。

这就要说 super() 的 C3 算法,它使用广度优先遍历的方法搜索 __mro__ ,这样 Grandson 中的 super() 调用了 Son.__init__() ,Son 中的 super() 调用了 Daughter.__init__() ,最后才是 Daughtersuper() 调用了 Parent.__init__()