Python super bypass MRO
-
21-12-2019 - |
Pregunta
Tengo una heredado de una clase y sobrescribir un método que también se hereda de una clase base.Pero la cosa es que la mitad método crea una excepción de la que me gustaría bypass llamando al primer método declarado.Es allí una manera de especificar la mro que omite el segundo llamadas?
Un ejemplo podría ser:
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
Muchas gracias
PD:Algo así como la clase BaseB(Base, BaseA) podría trabajar?
Solución
Normalmente te gustaría arreglar ese método en su lugar.
Sin embargo, el primer argumento a super()
es el lugar para comenzar a buscar el siguiente método de.Normalmente eso sería la clase actual, pero también puede pasar en la clase base:
class BaseB(BaseA):
def __init__(self):
res = super(BaseA, self).__init__()
Aquí, super()
toma el MRO de type(self)
, encuentra BaseA
en ese MRO, y ve a la siguiente clase la aplicación de __init__
.
Otra forma de eludir la problemática __init__
el método es simplemente llame al método independiente en Base
directamente:
class BaseB(BaseA):
def __init__(self):
res = Base.__init__(self)
eludiendo cualquier MRO búsquedas por completo.
Otros consejos
La Forma Correcta de solucionar este problema es crear una nueva jerarquía de clases que invalida el método infractor con una mejora de la aplicación.Si usted insiste en trucos, sin embargo, esto puede ser lo que usted desea:
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
Tenga en cuenta que yo estoy pidiendo para el super implementación con respecto a BaseA, lo que significa que la BaseA la aplicación no se utiliza nunca.
Sin embargo, este puede hacer lo correcto cuando diamante que es la herencia de los involucrados.Considere la posibilidad de:
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()
El resultado es :
initing BaseD
initing BaseB
initing Base
<__main__.BaseD object at 0x7f1e693a0110>
BaseC
se ha omitido aunque eso no es lo que queríamos.Esto es debido a que BaseC
entre vino BaseB
y BaseA
en el método de resolución de la orden, así que cuando nos hemos saltado de BaseB
a BaseA
que, sin querer, descuidado BaseC
.
>>> print [cls.__name__ for cls in BaseD.mro()]
['BaseD', 'BaseB', 'BaseC', 'BaseA', 'Base', 'object']
Cómo pelea solo
Base.__init__(self)