首頁  >  文章  >  後端開發  >  super在多繼承中的呼叫細節

super在多繼承中的呼叫細節

巴扎黑
巴扎黑原創
2016-11-26 09:56:291285瀏覽

註:此處以python 3為運作環境,範例摘自《python cookbook》第8章。 

python中若子類別要實現父類別的初始化,主要有兩種方法,第一種是直接透過父類別名,第二種是利用super方法。在單繼承時兩者沒什麼差別,但在多繼承時就需要注意一些細微的差距了。實例解釋才是硬道理!
1、使用父類別名稱的情況: 

Python代碼  

class Base:  

    def __  

  

class A(Base):  

def __init__(self):  

        Base.__init__(self)  

        

    def __init__(self):  

        Base.__init__(self)

        print('B.__init__')  

  

class C(A,B):      A.__init__(self)  

        B.__init__(self)  

    'C.__init__')  

此時實例化C類別會輸出如下: 

Python代碼  

>>> c 

Base.__init__  

B.__init__  


C.__init__  

>>>  

從中可以看出Base類別被調用了兩次。這想必在很多情況下都不是我們想要的結果,所以此時可考慮用super方法。

2、利用super的情況: 

Python代碼  

class Base:  

    def )  

  

class A(Base):  


    def __init__(self):  

        super().__init__()  

       

    def __init__(self):  

        super().__init__( )  

        print('B.__init__')  

  

class C(A,B):        super().__init__() # Only one call to super() here  

        print('C.__init__')  

此時再實例化C類的輸出為: 

P   

B.__init__  

A.__init__  

C.__init__  

>>>  

可看出Base類別是不是只調用了一次啊!但很遺憾的是,這並不是促使我寫這篇部落格記錄的原因,因為如果仔細觀察的話,雖說Base類的確如預期只調用了一次,但你有沒有發覺是先輸出“B.__init__”而後才輸出的「A.__init__」?而且為什麼這樣就使得Base只初始化了一次?想必你也有點懵逼了吧?其實這一切都得「怪罪」於super在多繼承時的呼叫過程。 python在實作一個類別(不只是繼承)時,會產生一個方法來產生解析順序列表,該列表可透過類別屬性__mro__ 查看之,如本例中是這樣的: 

>

Python程式碼  

>>> C.__mro__  

(,  

>>>  


所以在搜尋一個屬性或方法時,它就會按照這個列表遍歷每個類,直到找到第一個匹配這個屬性或方法的類為止。而在繼承中使用super時,解釋器會每遇到一次super就會在該列表上搜尋下一個類,直到不再遇到super或列表遍歷完為止,然後再類似遞歸逐層返回。因此本例中搜尋過程為:C中遇到super --> 搜尋列表中的下一個類,即A --> A中再次遇到super,搜尋B --> B中super再現,搜尋Base -- > 初始化Base類,遞歸回傳。
為了更好的解釋這個過程,現在請註解掉B類的super所在行: 

Python代碼  

class B(Base):  

#super().__init__( )  

        print('B.__init__')  

  

class C(A,B):        super().__init__() # Only one call to super() here  

        print('C.__init__')  

再次實例化C類,輸出如下: 

  

A.__init__  


C. __init__  

Base類別不再產生輸出!為什麼?因為B中沒了super後,就阻斷了清單去搜尋Base類,所以也就沒有初始化Base了!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn