内置的super()函数用于调用父类(超类)的一个方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
在Python中,super()有两个主要用例:
使我们避免显式使用基类名称
处理多重继承
在单继承的情况下,它允许我们通过引用基类super()。
class Mammal(object): def __init__(self, mammalName): print(mammalName, '是一种温血动物。') class Dog(Mammal): def __init__(self): print('狗有四条腿。') super().__init__('狗') d1 = Dog()
输出结果
狗有四条腿。 狗 是一种温血动物。
在这里,我们使用代码调用了Mammal类的__init__()方法(来自Dog类)
super().__init__('Dog')
代替
Mammal.__init__(self, 'Dog')
由于在调用成员时不需要指定基类的名称,因此可以轻松更改基类名称(如果需要)。
# 将基类更改为CanidaeFamily class Dog(CanidaeFamily): def __init__(self): print('狗有四条腿。') # 无需更改此 super().__init__('狗')super()内建返回一个代理对象,代替对象,可以通过委托调用基类的方法。这称为间接(使用super()引用基础对象的能力)
由于间接是在运行时计算的,因此我们可以在不同时间使用不同的基类(如果需要)。
class Animal: def __init__(self, Animal): print(Animal, '是动物'); class Mammal(Animal): def __init__(self, mammalName): print(mammalName, '是一种温血动物。') super().__init__(mammalName) class NonWingedMammal(Mammal): def __init__(self, NonWingedMammal): print(NonWingedMammal, "不会飞。") super().__init__(NonWingedMammal) class NonMarineMammal(Mammal): def __init__(self, NonMarineMammal): print(NonMarineMammal, "不会游泳。") super().__init__(NonMarineMammal) class Dog(NonMarineMammal, NonWingedMammal): def __init__(self): print('狗有4条腿。'); super().__init__('狗') d = Dog() print('') bat = NonMarineMammal('蝙蝠')
输出结果
狗有4条腿。 狗 不会游泳。 狗 不会飞。 狗 是一种温血动物。 狗 是动物 蝙蝠 不会游泳。 蝙蝠 是一种温血动物。 蝙蝠 是动物
方法解析顺序(MRO)是在存在多个继承的情况下应继承方法的顺序。您可以使用__mro__属性查看MRO 。
>>> Dog.__mro__ (<class 'Dog'>, <class 'NonMarineMammal'>, <class 'NonWingedMammal'>, <class 'Mammal'>, <class 'Animal'>, <class 'object'>)
这是MRO的工作方式:
派生调用中的方法总是在基类的方法之前调用。
在我们的示例中,在NonMarineMammal或NoneWingedMammal之前调用Dog类。 这两个类在Mammal之前调用,后者在Animal之前调用,而Animal类在对象(object)之前调用。
如果有多个父类,比如Dog(NonMarineMammal,NonWingedMammal)这样有多个父类,则首先调用NonMarineMammal的方法,因为它首先出现。