我見過super().__init__(*args)用來安全地呼叫超級建構式(以一種不會失敗鉆石繼承的方式)。但是,我找不到以這種方式呼叫具有不同引數的不同超級建構式的方法。
這是一個說明問題的示例。
from typing import TypeVar, Generic
X = TypeVar("X")
Y = TypeVar("Y")
class Base:
def __init__(self):
pass
class Left(Base, Generic[X]):
def __init__(self, x:X):
super().__init__()
self.lft = x
class TopRight(Base, Generic[Y]):
def __init__(self, y:Y):
super().__init__()
self.rgh = y
class BottomRight(TopRight[Y], Generic[Y]):
def __init__(self, y:Y):
super().__init__(y y)
class Root(Left[X], BottomRight[Y], Generic[X, Y]):
def __init__(self, x:X, y:Y):
pass #issue here
#does not work
#super().__init__(x)
#super().__init__(y)
#calls base twice
#Left[X].__init__(x)
#BottomRight[Y].__init__(y)
我如何打電話Left.__init__(x)和BottomRight.__init__(y)seperately和安全?
uj5u.com熱心網友回復:
問題是要以合作形式使用,中間類必須接受不是“針對”他們的引數,并super以透明的方式在他們自己的呼叫中傳遞這些引數。
你他們不會多次呼叫你的祖先類:你讓語言運行時為你做這件事。
你的代碼應該寫成:
from typing import Generic, TypeVar
X = TypeVar("X")
Y = TypeVar("Y")
class Base:
def __init__(self):
pass
class Left(Base, Generic[X]):
def __init__(self, x:X, **kwargs):
super().__init__(**kwargs)
self.lft = x
class TopRight(Base, Generic[Y]):
def __init__(self, y:Y, **kwargs):
super().__init__(**kwargs)
self.rgh = y
class BottomRight(TopRight[Y], Generic[Y]):
def __init__(self, y:Y, **kwargs): # <- when this is executed, "y" is extracted from kwargs
super().__init__(y=y y, **kwargs) # <- "x" remains in kwargs, but this class does not have to care about it.
class Root(Left[X], BottomRight[Y], Generic[X, Y]):
def __init__(self, x:X, y:Y):
super().__init__(x=x, y=y) # <- will traverse all superclasses, "Generic" being last
另外,請注意,根據專案的目的和最終的復雜性,這些型別注釋可能對您沒有任何幫助,反而會增加代碼的復雜性,否則很簡單。它們在 Python 專案中并不總是有益的,盡管由于環境原因,工具(即 IDE)可能會推薦它們。
另外,從幾天前檢查這個類似的答案,我是否詳細介紹了 Python 方法決議順序機制,并指向有關它們的官方檔案:在 Python 中的多重繼承中,父類 A 和 B 的初始化在同一時間?
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/381345.html
上一篇:無法在ADO.NET物體模型edmx中的類繼承中執行覆寫
下一篇:子類是新型別嗎?
