內(nèi)置的super()函數(shù)用于調(diào)用父類(超類)的一個方法。
super 是用來解決多重繼承問題的,直接用類名調(diào)用父類方法在使用單繼承的時候沒問題,但是如果使用多繼承,會涉及到查找順序(MRO)、重復(fù)調(diào)用(鉆石繼承)等種種問題。
MRO 就是類的方法解析順序表, 其實也就是繼承父類方法時的順序表。
在Python中,super()有兩個主要用例:
使我們避免顯式使用基類名稱
處理多重繼承
在單繼承的情況下,它允許我們通過引用基類super()。
class Mammal(object): def __init__(self, mammalName): print(mammalName, '是一種溫血動物。') class Dog(Mammal): def __init__(self): print('狗有四條腿。') super().__init__('狗') d1 = Dog()
輸出結(jié)果
狗有四條腿。 狗 是一種溫血動物。
在這里,我們使用代碼調(diào)用了Mammal類的__init__()方法(來自Dog類)
super().__init__('Dog')
代替
Mammal.__init__(self, 'Dog')
由于在調(diào)用成員時不需要指定基類的名稱,因此可以輕松更改基類名稱(如果需要)。
# 將基類更改為CanidaeFamily class Dog(CanidaeFamily): def __init__(self): print('狗有四條腿。') # 無需更改此 super().__init__('狗')super()內(nèi)建返回一個代理對象,代替對象,可以通過委托調(diào)用基類的方法。這稱為間接(使用super()引用基礎(chǔ)對象的能力)
由于間接是在運行時計算的,因此我們可以在不同時間使用不同的基類(如果需要)。
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('蝙蝠')
輸出結(jié)果
狗有4條腿。 狗 不會游泳。 狗 不會飛。 狗 是一種溫血動物。 狗 是動物 蝙蝠 不會游泳。 蝙蝠 是一種溫血動物。 蝙蝠 是動物
方法解析順序(MRO)是在存在多個繼承的情況下應(yīng)繼承方法的順序。您可以使用__mro__屬性查看MRO 。
>>> Dog.__mro__ (<class 'Dog'>, <class 'NonMarineMammal'>, <class 'NonWingedMammal'>, <class 'Mammal'>, <class 'Animal'>, <class 'object'>)
這是MRO的工作方式:
派生調(diào)用中的方法總是在基類的方法之前調(diào)用。
在我們的示例中,在NonMarineMammal或NoneWingedMammal之前調(diào)用Dog類。 這兩個類在Mammal之前調(diào)用,后者在Animal之前調(diào)用,而Animal類在對象(object)之前調(diào)用。
如果有多個父類,比如Dog(NonMarineMammal,NonWingedMammal)這樣有多個父類,則首先調(diào)用NonMarineMammal的方法,因為它首先出現(xiàn)。