Python中類(lèi)的mro與繼承關(guān)系詳解(二)
前言
版本:
- windows 10.0
- python 3.8
多重繼承
在Python數(shù)字比較與類(lèi)結(jié)構(gòu)中有簡(jiǎn)略提到類(lèi),且在Python中類(lèi)的mro與繼承關(guān)系詳解稍有解釋繼承關(guān)系,用到一個(gè)基類(lèi)Animal
如下:
class Animal: property_ = '能夠思考' def __init__(self, name, age, value): self.name_ = name self.age_ = age self.val_ = val
再定義Action
活動(dòng)作為另一個(gè)基類(lèi):
class Action: def __init__(self, action, val): self.action_ = action self.val_ = val
- 現(xiàn)在需定義一個(gè)
Dog
類(lèi),不僅是動(dòng)物,還能夠跑,可以來(lái)繼承上面兩個(gè)類(lèi)來(lái)定義:
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_': '跑'}
發(fā)現(xiàn)打印出的實(shí)例屬性,好像字典的鍵值更新,先初始化Animal時(shí),val傳入的值為79,而后被更新為78,這里為什么不能像繼承單個(gè)類(lèi)一樣直接用super方法代替呢。
上一篇有提到mro解析順序,可進(jìn)行嘗試,不重寫(xiě)__init__方法,發(fā)現(xiàn)Dog
類(lèi)只能傳入三個(gè)參數(shù),且都為Animal
類(lèi)的參數(shù),因?yàn)槔^承的兩個(gè)父類(lèi)都有該方法,優(yōu)先繼承左邊的父類(lèi)方法,如果想都繼承可以考慮這樣的形式,然而會(huì)提高后續(xù)維護(hù)的困難性。
可以將最左邊的父類(lèi)改成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]
- 祖孫類(lèi)
如再進(jìn)行繼承,視Dog
為父類(lèi),其Animal
,Action
都為祖父類(lèi),定義一個(gè)Pet
類(lèi):
class Pet(Dog): pass pet = Pet('大福', 8, '跑', 78)
傳入?yún)?shù),和實(shí)例化的對(duì)象跟Dog
一樣,如果需要改寫(xiě)某個(gè)方法,可以參照之前的方法進(jìn)行改寫(xiě),另外若在保留原方法的邏輯上進(jìn)行補(bǔ)充則用super方法。
Pet
類(lèi)的mro:
Pet.mro() # [__main__.Pet, __main__.Dog, __main__.Animal, __main__.Action, object]
思考片刻
通過(guò)上面的繼承及對(duì)應(yīng)的mro解析順序,可以思考以下通過(guò)多重繼承類(lèi)后,輸出的x屬性值為多少:
class Alpha: def __init__(self, val): self.x = val class Beta(Alpha): pass class Gamma: def __init__(self, val): self.x = val + 1 class Omega(Gamma): def __init__(self, val): super().__init__(val + 1) class Kappa(Beta, Omega): pass k = Kappa(1) print(k.x)
如果腦內(nèi)沒(méi)有一個(gè)mro解析順序圖,這里準(zhǔn)備了:
[__main__.Kappa, __main__.Beta, __main__.Alpha, __main__.Omega, __main__.Gamma, object]
這里或許會(huì)有疑問(wèn),Beta
后面不是Omega
嗎?怎么到Alpha
了,可以先看下Omega
,繼承Gamma
,而Gamma
跟Alpha
并不是同源的,類(lèi)似于Dog
類(lèi)的繼承,那么優(yōu)先就會(huì)使用Alpha
的__init__方法,所以在傳入?yún)?shù)值1的時(shí)候,僅運(yùn)行了Alpha
內(nèi)的self.x = val,屬性x被賦值成1,在最后print輸出即為1,打印結(jié)果檢查:
print(k.x) # 1
若把Gamma
類(lèi)改成繼承Alpha
類(lèi),再次猜測(cè)print(k.x)的值為多少?
class Alpha: def __init__(self, val): self.x = val class Beta(Alpha): pass class Gamma(Alpha): def __init__(self, val): self.x = val + 1 class Omega(Gamma): def __init__(self, val): super().__init__(val + 1) class Kappa(Beta, Omega): pass k = Kappa(1) print(k.x)
查看mro解析順序:
[__main__.Kappa, __main__.Beta, __main__.Omega, __main__.Gamma, __main__.Alpha, object]
此時(shí)發(fā)現(xiàn)Alpha
解析優(yōu)先級(jí)排在最后,Beta
跟Omega
可以看做是Beta
跟Gamma
的優(yōu)先級(jí)比較,因?yàn)?code>Omega繼承Gamma
,且重寫(xiě)了__init__方法,所以當(dāng)傳入?yún)?shù)時(shí)會(huì)對(duì)Gamma
類(lèi)的屬性進(jìn)行賦值,雖然Beta
類(lèi)直接繼承Alpha
,但Gamma
類(lèi)也直接繼承,所以Alpha
解析順序需要排在Gamma
后面,從而當(dāng)Kappa
類(lèi)傳入?yún)?shù)時(shí),經(jīng)過(guò)Omega
的super加1,傳入到Gamma處時(shí)為:self.x = val + 1中的val為2,輸出的k.x的值即為3,查看打印結(jié)果:
print(k.x) # 3
總結(jié)
通過(guò)連續(xù)兩篇對(duì)類(lèi)繼承及mro解析順序的說(shuō)明,理解類(lèi)在多重繼承中的變化,無(wú)論繼承多少遍,總歸要回歸本心,但也不能胡亂繼承,有條理的,有意義的繼承,才能讓自己乃至他人更好理解當(dāng)下寫(xiě)出的類(lèi)。
到此這篇關(guān)于Python中類(lèi)的mro與繼承關(guān)系詳解的文章就介紹到這了,更多相關(guān)Python mro內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5復(fù)選框控件QCheckBox詳細(xì)使用方法與實(shí)例
這篇文章主要介紹了python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5復(fù)選框控件QCheckBox詳細(xì)使用方法與實(shí)例,需要的朋友可以參考下2020-02-02python判斷設(shè)備是否聯(lián)網(wǎng)的方法
這篇文章主要為大家詳細(xì)介紹了python判斷設(shè)備是否聯(lián)網(wǎng)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06Python+Pygame實(shí)現(xiàn)海洋之神大冒險(xiǎn)游戲
這篇文章主要介紹了如何利用Python+Pygame自制一個(gè)海洋之神大冒險(xiǎn)游戲。規(guī)則是在海里收集魚(yú)骨頭,有些魚(yú)骨頭可以轉(zhuǎn)化為武器,用來(lái)攻擊敵人,感興趣的可以了解一下2022-08-08python熱力圖實(shí)現(xiàn)的完整實(shí)例
熱力圖的使用場(chǎng)景有描述數(shù)據(jù)在空間的密集程度,常見(jiàn)有城市熱力圖、區(qū)域熱力圖,描述多個(gè)變量之間相關(guān)性高低程度,這篇文章主要給大家介紹了關(guān)于python熱力圖實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2022-06-06Python實(shí)現(xiàn)備份文件實(shí)例
這篇文章主要介紹了Python實(shí)現(xiàn)備份文件的方法,可實(shí)現(xiàn)針對(duì)各類(lèi)常見(jiàn)擴(kuò)展名的文件進(jìn)行備份的功能,需要的朋友可以參考下2014-09-09Python 實(shí)現(xiàn)自動(dòng)化Excel報(bào)表的步驟
這篇文章主要介紹了Python 實(shí)現(xiàn)自動(dòng)化Excel報(bào)表的步驟,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下2021-04-04