Python スーパーバイパス MRO
-
21-12-2019 - |
質問
クラスを継承し、基本クラスから継承したメソッドを上書きしました。しかし、問題は、中間のメソッドが最初に宣言されたメソッドを呼び出すことでバイパスしたい例外を作成するということです。に指定する方法はありますか さん 2回目の呼び出しは無視されますか?
例としては次のようなものが考えられます。
class Base(object):
def __init__(self):
res = "Want this"
print res
class BaseA(Base):
def __init__(self):
res = super(BaseA, self).__init__()
res = "Not this"
print res
class BaseB(BaseA):
def __init__(self):
res = super(BaseB, self).__init()
#At this poing res is "Not this"
#The desire is that it would be "Want this"
print res
どうもありがとう
PD:クラスBaseB(Base, BaseA)のようなものは機能するでしょうか?
解決
通常は代わりにその方法を修正します。
しかし、super()
の最初の引数は、から次の方法の検索を開始する場所です。通常、それは現在のクラスですが、基本クラスを渡すこともできます。
class BaseB(BaseA):
def __init__(self):
res = super(BaseA, self).__init__()
.
ここでは、super()
はtype(self)
のMROを取り、そのMROのBaseA
を見つけ、次のクラスを実装します。
問題のある__init__
メソッドをバイパスするもう1つの方法は、__init__
で直接の未結合メソッドを呼び出すだけです。
class BaseB(BaseA):
def __init__(self):
res = Base.__init__(self)
.
すべてのMRO検索を完全に迂回します。
他のヒント
これを修正する正しい方法は、改善された実装で問題のある方法をオーバーライドする新しいクラス階層を作成することです。あなたがハッキーを主張した場合、これはあなたが望むものかもしれません:
class BaseB(BaseA):
def __init__(self):
res = super(BaseA, self).__init()
#At this poing res is "Not this"
#The desire is that it would be "Want this"
print res
.
基礎に関する超実装を求めることに注意してください。これは、基本実装が決して使用されないことを意味します。
しかし、このは、ダイヤモンドの継承が関与しているときに間違ったことを行うことができます。検討してください:
class Base(object):
def __init__(self):
print 'initing Base'
class BaseA(Base):
def __init__(self):
print 'initing BaseA'
res = super(BaseA, self).__init__()
class BaseB(BaseA):
def __init__(self):
print 'initing BaseB'
res = super(BaseA, self).__init__()
class BaseC(BaseA):
def __init__(self):
print 'initing BaseC'
res = super(BaseC, self).__init__()
class BaseD(BaseB, BaseC):
def __init__(self):
print 'initing BaseD'
res = super(BaseD, self).__init__()
print BaseD()
.
出力は次のとおりです。
initing BaseD
initing BaseB
initing Base
<__main__.BaseD object at 0x7f1e693a0110>
.
BaseC
は、それが私たちが望んでいるものではなくスキップされました。これは、BaseC
とメソッドの解像度の順序でBaseB
とBaseA
の間に起こるため、BaseB
からBaseA
にスキップされると、誤ってBaseC
が無視されます。
>>> print [cls.__name__ for cls in BaseD.mro()]
['BaseD', 'BaseB', 'BaseC', 'BaseA', 'Base', 'object']
. どうだろう
Base.__init__(self)