簡體   English   中英

關於Python超倍數inheritance的問題

[英]Question on Python super multiple inheritance

我是 Python 的新手,我真的對超級 function 和多個 inheritance 感到困惑。

這是玩具代碼:

class A():
    def __init__(self):
        print('Call class A')        
        print('Leave class A')

class C(A):
    def __init__(self):
        print('Call class C')
        A.__init__(self)
        print('Leave class C')
class D(A):
    def __init__(self):
        print('Call class D')
        #A.__init__(self)
        super(D,self).__init__()
        print('Leave class D')
class B(A):
    def __init__(self):
        print('Call class B')
        super(B,self).__init__()
        print('Leave class B')

class E(C,B,D):
    def __init__(self):
        print('Call class E')
        B.__init__(self)
        #C.__init__(self)
        #D.__init__(self)
        print('Leave class E')

那么output就是:

Call class E
Call class B
Call class D
Call class A
Leave class A
Leave class D
Leave class B
Leave class E
(<class '__main__.E'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>)

其中 Class D 的__init__被調用。 但是,如果我將 class E 更改為:

class E(B,C,D):
    def __init__(self):
        print('Call class E')
        B.__init__(self)
        #C.__init__(self)
        #D.__init__(self)
        print('Leave class E')

其中 B,C,D 的順序發生變化,則 output 為:

Call class E
Call class B
Call class C
Call class A
Leave class A
Leave class C
Leave class B
Leave class E
(<class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>)

那么class D的__init__不會被調用,而是class的C的,雖然class沒有使用super的ZC1C425268E68398DZ。

有誰知道: 1.在第一個代碼中,為什么 class D 的__init__也被調用? 2、第二段代碼為什么調用了class C的__init__而沒有調用class D的__init__

未能始終如一地使用super意味着您不能保證 MRO 將正確行走。

在您的第一個示例中,在E.__init__中對B.__init__的顯式調用確保C.__init__永遠不會被調用,因為B在 MRO 中位於C之后。

在第二個示例中, B恰好是E之后的下一個 class ,所以沒有任何問題(還)。 但是隨后在C.__init__中,您再次使用A.__init__(self)而不是super(C, self).__init__() ,這意味着您直接從C跳到A ,繞過D應該是下一個。

在設計使用super (不僅僅是單個類)的 class層次結構時,您必須確保每個class 都使用super以確保遵循運行時類型self選擇的 MRO,而不是對父 ZA2F2ED4F8EBC2CBB4C21A2DC 方法的硬編碼調用在編譯時。

正確的定義是

class A:
    def __init__(self):
        print('Call class A')
        super().__init__()       
        print('Leave class A')

class C(A):
    def __init__(self):
        print('Call class C')
        super().__init__()
        print('Leave class C')
class D(A):
    def __init__(self):
        print('Call class D')
        super().__init__()
        print('Leave class D')
class B(A):
    def __init__(self):
        print('Call class B')
        super().__init__()
        print('Leave class B')

class E(C,B,D):
    def __init__(self):
        print('Call class E')
        super().__init__(self)
        print('Leave class E')

在 Python 3 中,一些編譯器魔法在沒有任何調用super時提供“默認” arguments。 例如,在E.__init__中, super().__init___()等價於super(C, self).__init__()

因為self的值(以及它的類型)在整個調用鏈中是恆定的,所以super()的每次使用指的是 MRO 中type(self)的下一個 class 。 在上面的例子中,這將產生 output

Call class E
Call class C
Call class B
Call class D
Call class A
Leave class A
Leave class D
Leave class B
Leave class C
Leave class E

如果您更改E定義中基類的順序,則 MRO(以及輸出)將自動更新,而無需更改任何進一步的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM