簡體   English   中英

關於 python 3.x MRO 和“super()”的問題

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

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