[英]How to call “overriden” methods from both parent classes?
考慮以下類,其中P1
和P2
是C
的父類:
class P1:
def f(self):
print('P1')
class P2:
def f(self):
print('P2')
class C(P1, P2):
def f(self):
print('C')
# super().f()
# super(P1, self).f()
c = C()
c.f()
當我運行它時,它會打印C
。
如果我取消注釋第一行super().f()
,那么它也會打印P1
因為super()
將從直接父P1
調用該方法
如果我取消注釋第二行super(P1, self).f()
,那么它也會打印P2
因為super(P1, self)
將從P1
的兄弟P2
調用該方法
我想知道的是,是否有任何方法可以通過一次調用super()
function 從父類P1
和P2
調用f
方法,而不是像我一樣調用它兩次。
或者,有沒有其他方法可以在不使用super
function 的情況下做到這一點?
沒有什么好方法可以完全按照您的意願行事。 但是,如果您可以同時修改P1
和P2
,則可以實現協作多個 inheritance,您只需將基礎 class 添加到具有該方法的無操作實現的兩個父類:
class GP: # grandparent base class
def f(self):
pass # do nothing
class P1(GP):
def f(self):
print("P1")
super().f()
class P2(GP):
def f(self):
print("P2")
super().f()
class C(P1, P2):
def f(self):
print("C")
super().f()
這是有效的,因為super
並不完全意味着“我的父類”。 這意味着“此對象的 MRO 中的下一個”。 MRO 是 Method Resolution Order,基本上是在 inheritance 中搜索的順序。 當在C
中調用super()
時,它會在P1
中找到方法。 但是當在P1
中調用super()
時(在C
的實例上),它會調用P2
,因為C
實例的 MRO 是[C, P1, P2, GP, object]
。 P2
在P1
之后,所以它被第二個super
調用選中。
需要GP
class 來結束super
調用鏈。 如果你沒有它,最后一個super
調用將解析為object
(這是所有 inheritance 樹的根),由於沒有這樣的方法,你會得到一個錯誤。 基本 class 中的實現不需要什么都不做,它只需要最后不調用super
。
Super 從派生的 class 的方法解析順序(MRO)調用下一個方法。
f 方法的每一個實現都應該調用 super,父類之間不需要相互了解,super 會自動調用 MRO 中的 next 方法。
編輯:我忘記了 mro 中的最后一個 class 始終是 object。 object 沒有名為 f 的方法。 因此,您應該注意 mro 中具有該方法的最后一個 class 要么不調用 super().f,要么捕獲 AttributeError。
只要遵循 C3 線性化規則,子 class 就可以更改 MRO。 這意味着派生的 class 決定了哪些代碼可以運行,哪些代碼不能運行。 這是依賴注入的一種方式。
您可以通過 __mro__ 屬性檢查 class 的 MRO。
這個答案主要基於 Raymond Hettinger認為 super的談話
class P1:
def f(self):
super().f()
print('P1')
class P2:
def f(self):
print('P2')
class C(P1, P2):
def f(self):
super().f()
print('C')
class C2(P2, P1):
def f(self):
super().f()
print('C2')
>>> C().f()
P2
P1
C
>>> C2().f()
P2
C2
>>> C.__mro__
(<class '__main__.C'>, <class '__main__.P1'>, <class '__main__.P2'>, <type 'object'>)
>>> C2.__mro__
(<class '__main__.C2'>, <class '__main__.P2'>, <class '__main__.P1'>, <type 'object'>)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.