目錄
前言
版本:
- windows 10.0
- python 3.8
多重繼承
在Python數字比較與類結構中有簡略提到類,且在Python中類得mro與繼承關系詳解稍有解釋繼承關系,用到一個基類Animal
如下:
class Animal: property_ = '能夠思考' def __init__(self, name, age, value): self.name_ = name self.age_ = age self.val_ = val
再定義Action
活動作為另一個基類:
class Action: def __init__(self, action, val): self.action_ = action self.val_ = val
- 現在需定義一個
Dog
類,不僅是動物,還能夠跑,可以來繼承上面兩個類來定義:
class Dog(Animal, Action): def __init__(self, name, age, action, val): Animal.__init__(self, name, age, val+1) Action.__init__(self, action, val)dog = Dog('大福', 8, '跑', 78)print(dog.__dict__)# {'name_': '大福', 'age_': 8, 'val_': 78, 'action_': '跑'}
發現打印出得實例屬性,好像字典得鍵值更新,先初始化Animal時,val傳入得值為79,而后被更新為78,這里為什么不能像繼承單個類一樣直接用super方法代替呢。
上一篇有提到mro解析順序,可進行嘗試,不重寫__init__方法,發現Dog
類只能傳入三個參數,且都為Animal
類得參數,因為繼承得兩個父類都有該方法,優先繼承左邊得父類方法,如果想都繼承可以考慮這樣得形式,然而會提高后續維護得困難性。
可以將最左邊得父類改成super方式:
class Dog(Animal, Action): def __init__(self, name, age, action, val): super().__init__(name, age, val+1) Action.__init__(self, action, val)
mro解析順序,與上面所述一致:
Dog.mro()# [__main__.Dog, __main__.Animal, __main__.Action, object]
- 祖孫類
如再進行繼承,視Dog
為父類,其Animal
,Action
都為祖父類,定義一個Pet
類:
class Pet(Dog): passpet = Pet('大福', 8, '跑', 78)
傳入參數,和實例化得對象跟Dog
一樣,如果需要改寫某個方法,可以參照之前得方法進行改寫,另外若在保留原方法得邏輯上進行補充則用super方法。
Pet
類得mro:
Pet.mro()# [__main__.Pet, __main__.Dog, __main__.Animal, __main__.Action, object]
思考片刻
通過上面得繼承及對應得mro解析順序,可以思考以下通過多重繼承類后,輸出得x屬性值為多少:
class Alpha: def __init__(self, val): self.x = valclass Beta(Alpha): passclass Gamma: def __init__(self, val): self.x = val + 1class Omega(Gamma): def __init__(self, val): super().__init__(val + 1)class Kappa(Beta, Omega): passk = Kappa(1)print(k.x)
如果腦內沒有一個mro解析順序圖,這里準備了:
[__main__.Kappa, __main__.Beta, __main__.Alpha, __main__.Omega, __main__.Gamma, object]
這里或許會有疑問,Beta
后面不是Omega
嗎?怎么到Alpha
了,可以先看下Omega
,繼承Gamma
,而Gamma
跟Alpha
并不是同源得,類似于Dog
類得繼承,那么優先就會使用Alpha
得__init__方法,所以在傳入參數值1得時候,僅運行了Alpha
內得self.x = val,屬性x被賦值成1,在最后print輸出即為1,打印結果檢查:
print(k.x)# 1
若把Gamma
類改成繼承Alpha
類,再次猜測print(k.x)得值為多少?
class Alpha: def __init__(self, val): self.x = valclass Beta(Alpha): passclass Gamma(Alpha): def __init__(self, val): self.x = val + 1class Omega(Gamma): def __init__(self, val): super().__init__(val + 1)class Kappa(Beta, Omega): passk = Kappa(1)print(k.x)
查看mro解析順序:
[__main__.Kappa, __main__.Beta, __main__.Omega, __main__.Gamma, __main__.Alpha, object]
此時發現Alpha
解析優先級排在最后,Beta
跟Omega
可以看做是Beta
跟Gamma
得優先級比較,因為Omega
繼承Gamma
,且重寫了__init__方法,所以當傳入參數時會對Gamma
類得屬性進行賦值,雖然Beta
類直接繼承Alpha
,但Gamma
類也直接繼承,所以Alpha
解析順序需要排在Gamma
后面,從而當Kappa
類傳入參數時,經過Omega
得super加1,傳入到Gamma處時為:self.x = val + 1中得val為2,輸出得k.x得值即為3,查看打印結果:
print(k.x)# 3
總結
通過連續兩篇對類繼承及mro解析順序得說明,理解類在多重繼承中得變化,無論繼承多少遍,總歸要回歸本心,但也不能胡亂繼承,有條理得,有意義得繼承,才能讓自己乃至他人更好理解當下寫出得類。
到此這篇關于Python中類得mro與繼承關系詳解得內容就介紹到這了,更多相關Python mro內容請搜索之家以前得內容或繼續瀏覽下面得相關內容希望大家以后多多支持之家!