[英]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.