[英]question regarding python 3.x MRO and "super()"
此代碼顯示錯誤:AttributeError: 'super' object has no attribute 'method'
當在 class C中刪除“super.method()”時,同樣的代碼不會顯示錯誤。為什么?
class A(object):
def method(self):
print("\n class A method")
super().method()
class B(object):
def method(self):
print("\n class B method")
super().method()
class C(object):
def method(self):
print("\n class C method")
super().method()
class X(A, B):
def method(self):
print("\n class X method")
super().method()
class Y(B, C):
def method(self):
print("\n class Y method")
super().method()
class P(X, Y, C):
def method(self):
print("\n class P method")
super().method()
p = P()
p.method()
print(P.mro())
我想知道,為什么這個程序在 class C 中包含“super().method”時顯示錯誤,為什么在 class C 中刪除“super().method”時這個程序不顯示錯誤?
這不是錯誤,而是使用多個 inheritance 和super
的功能。 讓我一一回答你的問題:
為什么這個程序在 class C 中包含“super().method”時顯示錯誤?
原因是基類 class object
沒有名為method
的方法。 調用C().method()
或簡單地object().method()
時,您會看到相同的異常。 所以我想這是意料之中的。
為什么同一個程序在 class C 中刪除“super().method”時不顯示錯誤?
這就是python的方法解析順序(MRO)的神奇之處。 如果你執行
print(P.mro())
你應該看到
[__main__.P,
__main__.X,
__main__.A,
__main__.Y,
__main__.B,
__main__.C,
object]
在這里,你看到super
調用不會調用一個 class 的所有父代,直到 inheritance 樹的頂部,然后取下一個 class。相反,它會根據它們的“代”來調用它們。
看下面的例子:
class Base:
def method(self):
print("Base")
class ParentA(Base):
def method(self):
print('Parent A')
super().method()
class ParentB(Base):
def method(self):
print("Parent B")
class Child(ParentA, ParentB):
def method(self):
print("Child")
super().method()
print(Child.mro())
Child().method()
哪個會給你
[<class '__main__.Child'>, <class '__main__.ParentA'>, <class '__main__.ParentB'>, <class '__main__.Base'>, <class 'object'>]
Child
Parent A
Parent B
您看不到Base
行,因為ParentB
中的super
由於存在共享相同基數的ParentA
而被忽略。
但是,如果您交換 inheritance,您將看到打印的Base
行。 簡而言之,遵循MRO,但如果一代中的最后一個class不調用super,則鏈停止。
我同意這不直觀,但在實踐中這很少成為問題,或者如果您必須考慮 MRO 來理解代碼,這將是重構的一個很好的候選者。
要了解 MRO,我建議閱讀https://en.wikipedia.org/wiki/C3_linearization或 SO 上的其他相關問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.