Python-Super-Bypass-MRO
-
21-12-2019 - |
Frage
Ich habe eine Klasse geerbt und eine Methode überschrieben, die auch von einer Basisklasse geerbt wurde.Aber die Sache ist, dass die mittlere Methode eine Ausnahme erzeugt, die ich umgehen möchte, indem ich die erste deklarierte Methode aufrufe.Gibt es eine Möglichkeit, dem anzugeben mro das ignoriert die zweiten Anrufe?
Ein Beispiel könnte sein:
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
Danke schön
PD:So etwas wie class BaseB(Base, BaseA) könnte funktionieren?
Lösung
Normalerweise sie würden stattdessen diese Methode reparieren.
Das erste Argument für super()
ist der Ort, an dem Sie nach der nächsten Methode suchen können von.Normalerweise wäre das die aktuelle Klasse, aber Sie können auch die Basisklasse übergeben:
class BaseB(BaseA):
def __init__(self):
res = super(BaseA, self).__init__()
Hier, super()
übernimmt die MRO von type(self)
, finden BaseA
in diesem MRO und sucht nach der nächsten implementierenden Klasse __init__
.
Eine andere Möglichkeit, das Problem zu umgehen __init__
methode besteht darin, einfach die ungebundene Methode aufzurufen Base
direkt:
class BaseB(BaseA):
def __init__(self):
res = Base.__init__(self)
Umgehung jeglicher MRO-Suche vollständig.
Andere Tipps
Der richtige Weg, dies zu beheben, besteht darin, eine neue Klassenhierarchie zu erstellen, die die fehlerhafte Methode mit einer verbesserten Implementierung überschreibt.Wenn Sie jedoch auf Hacker bestehen, könnte dies das sein, was Sie wollen:
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
Beachten Sie, dass ich nach der Superimplementierung in Bezug auf BaseA frage, was bedeutet, dass die BaseA-Implementierung niemals verwendet wird.
Dies ist jedoch können tun Sie das Falsche, wenn es um die Vererbung von Diamanten geht.Betrachten:
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()
Die Ausgabe ist :
initing BaseD
initing BaseB
initing Base
<__main__.BaseD object at 0x7f1e693a0110>
BaseC
wurde übersprungen, obwohl wir das nicht wollten.Dies liegt daran, dass BaseC
kam zwischen BaseB
und BaseA
in der Reihenfolge der Methodenauflösung, also wenn wir von übersprungen haben BaseB
zu BaseA
wir haben versehentlich vernachlässigt BaseC
.
>>> print [cls.__name__ for cls in BaseD.mro()]
['BaseD', 'BaseB', 'BaseC', 'BaseA', 'Base', 'object']
wie du gerade bin
Base.__init__(self)