Python Super Bypass MRO
-
21-12-2019 - |
Domanda
Ho una classe ereditata e sovrascritta un metodo che è anche ereditato da una classe base.Ma la cosa è che il metodo centrale crea un'eccezione che vorrei bypassare chiamando il primo metodo dichiarato.C'è un modo per specificare il MRO che ignora le seconde chiamate?
Un esempio potrebbe essere:
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
.
Grazie mille
PD: Qualcosa come la classe baseb (base, basea) potrebbe funzionare?
Soluzione
Normalmente si risolve il metodo.
Tuttavia, il primo argomento a super()
è il posto dove iniziare la ricerca del metodo successivo da .Normalmente sarebbe la classe attuale, ma puoi anche passare nella classe base:
class BaseB(BaseA):
def __init__(self):
res = super(BaseA, self).__init__()
.
Qui, super()
prende la MRO di type(self)
, trova BaseA
in quella MRO e cerca la prossima esecuzione della classe Implementazione __init__
.
Un altro modo per bypassare il metodo problematico __init__
è quello di chiamare direttamente il metodo non legato su Base
direttamente:
class BaseB(BaseA):
def __init__(self):
res = Base.__init__(self)
.
Bypassare qualsiasi MRO cerca interamente.
Altri suggerimenti
Il modo giusto per risolvere questo è creare una nuova gerarchia di classe che sovrascrive il metodo di offensivo con un'implementazione migliorata.Se insisti sul hackery, però, questo potrebbe essere quello che vuoi:
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
.
Nota che sto chiedendo la super implementazione rispetto alla Basea, il che significa che l'implementazione della Basea non viene mai utilizzata.
.
Tuttavia, questo può fare la cosa sbagliata quando è coinvolta l'ereditarietà del diamante.Considera:
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()
.
L'output è:
initing BaseD
initing BaseB
initing Base
<__main__.BaseD object at 0x7f1e693a0110>
.
BaseC
è stato saltato anche se non è quello che volevamo.Questo perché BaseC
è arrivato tra BaseB
e BaseA
nell'ordine del metodo di risoluzione, quindi quando abbiamo saltato da BaseB
a BaseA
abbiamo inavvertitamente trascurato BaseC
.
>>> print [cls.__name__ for cls in BaseD.mro()]
['BaseD', 'BaseB', 'BaseC', 'BaseA', 'Base', 'object']
. Come BOUT
Base.__init__(self)