首先来一段单继承中使用 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__()
是可以的,分别调用了 Son
和 Daughter
的构造方法。
下面再改一下,如果是存在菱形继承的多继承呢?
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__()
的形式可以吗?
不可以,你可以自己试试,结果还是一样的。
解决方法是把 Grandson
中 super(Son, self).__init__()
这条语句删掉即可。
这就要说 super()
的 C3 算法,它使用广度优先遍历的方法搜索 __mro__
,这样 Grandson
中的 super()
调用了 Son.__init__()
,Son 中的 super()
调用了 Daughter.__init__()
,最后才是 Daughter
的 super()
调用了 Parent.__init__()
。