Python中類的mro與繼承關系詳解(二)
前言
版本:
- windows 10.0
- python 3.8
多重繼承
在Python數(shù)字比較與類結構中有簡略提到類,且在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- 現(xiàn)在需定義一個
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_': '跑'}發(fā)現(xiàn)打印出的實例屬性,好像字典的鍵值更新,先初始化Animal時,val傳入的值為79,而后被更新為78,這里為什么不能像繼承單個類一樣直接用super方法代替呢。
上一篇有提到mro解析順序,可進行嘗試,不重寫__init__方法,發(fā)現(xiàn)Dog類只能傳入三個參數(shù),且都為Animal類的參數(shù),因為繼承的兩個父類都有該方法,優(yōu)先繼承左邊的父類方法,如果想都繼承可以考慮這樣的形式,然而會提高后續(xù)維護的困難性。
可以將最左邊的父類改成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):
pass
pet = Pet('大福', 8, '跑', 78)傳入?yún)?shù),和實例化的對象跟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 = 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)沒有一個mro解析順序圖,這里準備了:
[__main__.Kappa, __main__.Beta, __main__.Alpha, __main__.Omega, __main__.Gamma, object]
這里或許會有疑問,Beta后面不是Omega嗎?怎么到Alpha了,可以先看下Omega,繼承Gamma,而Gamma跟Alpha并不是同源的,類似于Dog類的繼承,那么優(yōu)先就會使用Alpha的__init__方法,所以在傳入?yún)?shù)值1的時候,僅運行了Alpha內(nèi)的self.x = val,屬性x被賦值成1,在最后print輸出即為1,打印結果檢查:
print(k.x) # 1
若把Gamma類改成繼承Alpha類,再次猜測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]
此時發(fā)現(xiàn)Alpha解析優(yōu)先級排在最后,Beta跟Omega可以看做是Beta跟Gamma的優(yōu)先級比較,因為Omega繼承Gamma,且重寫了__init__方法,所以當傳入?yún)?shù)時會對Gamma類的屬性進行賦值,雖然Beta類直接繼承Alpha,但Gamma類也直接繼承,所以Alpha解析順序需要排在Gamma后面,從而當Kappa類傳入?yún)?shù)時,經(jīng)過Omega的super加1,傳入到Gamma處時為:self.x = val + 1中的val為2,輸出的k.x的值即為3,查看打印結果:
print(k.x) # 3
總結
通過連續(xù)兩篇對類繼承及mro解析順序的說明,理解類在多重繼承中的變化,無論繼承多少遍,總歸要回歸本心,但也不能胡亂繼承,有條理的,有意義的繼承,才能讓自己乃至他人更好理解當下寫出的類。
到此這篇關于Python中類的mro與繼承關系詳解的文章就介紹到這了,更多相關Python mro內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python爬取股票最新數(shù)據(jù)并用excel繪制樹狀圖的示例
這篇文章主要介紹了python爬取股票最新數(shù)據(jù)并用excel繪制樹狀圖的示例,幫助大家更好的理解和學習使用python,感興趣的朋友可以了解下2021-03-03
在Python3中使用asyncio庫進行快速數(shù)據(jù)抓取的教程
這篇文章主要介紹了在Python3中使用asyncio進行快速數(shù)據(jù)抓取,asyncio是一個異步IO庫,運行效率較高,需要的朋友可以參考下2015-04-04
Django表單提交后實現(xiàn)獲取相同name的不同value值
這篇文章主要介紹了Django表單提交后實現(xiàn)獲取相同name的不同value值,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-05-05
Python已解決NameError: name ‘xxx‘ is not&nb
本文主要介紹了Python已解決NameError: name ‘xxx‘ is not defined,解決報錯NameError: name 'xxx' is not defined的關鍵在于仔細檢查拼寫、作用域和賦值等問題,感興趣的可以了解一下2024-06-06
python神經(jīng)網(wǎng)絡pytorch中BN運算操作自實現(xiàn)
這篇文章主要為大家介紹了python神經(jīng)網(wǎng)絡pytorch中BN運算操作自實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05
Python獲取命令實時輸出-原樣彩色輸出并返回輸出結果的示例
今天小編就為大家分享一篇Python獲取命令實時輸出-原樣彩色輸出并返回輸出結果的示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-07-07

