python 在類的繼承中,當前類中如果方法與基類(父類)的方法一樣,會覆蓋基類的方法。
class Base(object): def run(self): print("Base start running~~") class Dog(Base): def run(self): print("Dog start running~~") if __name__ == "__main__": Dog().run() # 結果 Dog start running~~ Process finished with exit code 0
上面代碼代碼中,基類Base 並沒有執行,但是有些時候,定義基類就是把共同的代碼寫在一起,在調用當前方法是,我們基類中已經實現的公共部分。
類的繼承
- 經典類(classic class) 基類名.方法名(self, *args, **kwargs), python版本低於2.2
- 新式類(new-style class) super(當前類名, self).方法名(*args, **kwargs), python 版本大於2.2
1 class Base(object): 2 def run(self): 3 print("Now start running~~") 4 5 class Dog(Base): 6 def run(self): 7 Base.run(self) # 經典類繼承 8 print("Dog start running~~") 9 10 if __name__ == "__main__": 11 Dog().run() 12 13 # 結果 14 Now start running~~ 15 Dog start running~~ 16 17 Process finished with exit code 0
當使用經典類繼承時,Dog->Base->object 這種簡單的繼承順序還可以,如果出現多重繼承時,就會有下面的結果:
1 class Base(object): 2 def __init__(self): 3 print("進入Base 類") 4 5 6 class A(Base): 7 def __init__(self): 8 print("進入A 類") 9 Base.__init__(self) 10 11 12 class B(Base): 13 def __init__(self): 14 print("進入B 類") 15 Base.__init__(self) 16 17 18 class C(A, B): 19 def __init__(self): 20 print("進入C 類") 21 A.__init__(self) 22 B.__init__(self) 23 24 25 if __name__ == "__main__": 26 c = C()
運行結果:
1 進入C 類 2 進入A 類 3 進入Base 類 4 進入B 類 5 進入Base 類 6 7 Process finished with exit code 0
我們不難發現,執行順序: C -> A -> Base -> B -> Base
是不是順序有點蒙,我們理想狀態的順序難道不應該是: C -> A -> B -> Base (在繼承多個類時,繼承順序從左往右依次繼承)
如果按照理想狀態運行應該怎么辦, 我們就要用到 super 了。
super() 使用:
1 class Base(object): 2 def __init__(self): 3 print("進入Base 類") 4 5 6 class A(Base): 7 def __init__(self): 8 print("進入A 類") 9 super(A, self).__init__() # python2.7 的寫法 10 11 12 class B(Base): 13 def __init__(self): 14 print("進入B 類") 15 super().__init__() 16 17 18 class C(A, B): 19 def __init__(self): 20 print("進入C 類") 21 super().__init__() # python3 繼承的寫法 22 23 24 if __name__ == "__main__": 25 c = C()
結果:
1 進入C 類 2 進入A 類 3 進入B 類 4 進入Base 類 5 6 Process finished with exit code 0
這樣是不是就跟我們預想的一致了。
下面簡單說一下super 是怎么運行的:
MRO
簡單說一下 MRO(Method Resolution Order),中文可以叫做 方法解析順序, 在方法調用時,需要對當前類以及基類進行搜索確定方法位置。
在程序中可以使用:
print(C.mro())
結果:
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]
python MRO
- 經典類的深度遍歷
- python2 新式類的預計算
- python3 新式類的C3線性化計算
python3 統一使用 C3 線性化算法,有興趣的可以自行搜索。
小結
- 在super機制里可以保證公共父類僅被執行一次
- 執行的順序,是按照MRO:方法解析順序 進行的,執行完當前類按照mro 順序執行下個類。