herencia multiple python
Python multi-herencia,__init__ (3)
Mira este ejemplo:
class Base(object):
def __init__(self, c):
print(''Base called by {0}''.format(c))
super().__init__()
class ParentA(Base):
def __init__(self, c):
print(''ParentA called by {0}''.format(c))
super().__init__(''ParentA'')
class ParentB(Base):
def __init__(self, c):
print(''ParentB called by {0}''.format(c))
super().__init__(''ParentB'')
class Child(ParentA, ParentB):
def __init__(self, c):
print(''Child called by {0}''.format(c))
super().__init__(''Child'')
Child(''Construct'')
print(Child.mro())
Esto dará como resultado:
Child called by Construct
ParentA called by Child
ParentB called by ParentA
Base called by ParentB
[<class ''__main__.Child''>, <class ''__main__.ParentA''>, <class ''__main__.ParentB''>, <class ''__main__.Base''>, <class ''object''>]
La herencia múltiple de Python es como una cadena, en Child
clase Child
mro
, la ParentA
de ParentA
es ParentB
, por lo que necesita llamar a super().__init__()
en ParentA
para ParentB
.
Si cambia super().__init__(''ParentA'')
a Base.__init__(self, ''ParentA'')
, esto romperá la cadena de herencia, y generará:
Child called by Construct
ParentA called by Child
Base called by ParentA
[<class ''__main__.Child''>, <class ''__main__.ParentA''>, <class ''__main__.ParentB''>, <class ''__main__.Base''>, <class ''object''>]
Más información acerca de MRO
En cuanto a la herencia de padres múltiples, cuando llamo al super
. __init__
, ¿por qué no se llama a la función __init__ de __init__
? Gracias.
class parent(object):
var1=1
var2=2
def __init__(self,x=1,y=2):
self.var1=x
self.var2=y
class parent2(object):
var4=11
var5=12
def __init__(self,x=3,y=4):
self.var4=x
self.var5=y
def parprint(self):
print self.var4
print self.var5
class child(parent, parent2):
var3=5
def __init__(self,x,y):
super(child, self).__init__(x,y)
childobject = child(9,10)
print childobject.var1
print childobject.var2
print childobject.var3
childobject.parprint()
La salida es
9
10
5
11
12
Porque el parent
es el siguiente en la orden de resolución de métodos (MRO) , y nunca usa super()
para llamar a parent2
.
Si desea utilizar super
en child
para llamar al parent.__init__
y parent2._init__
, ambos padres __init__
s también deben llamar a super
:
class parent(Base):
def __init__(self,x=1,y=2):
super(parent,self).__init__(x,y)
class parent2(Base):
def __init__(self,x=3,y=4):
super(parent2,self).__init__(x,y)
Consulte "Super método de Python y alternativas de llamada" para obtener más detalles sobre la secuencia de llamadas a __init__
causadas por el uso de super
.
class Base(object):
def __init__(self,*args):
pass
class parent(Base):
var1=1
var2=2
def __init__(self,x=1,y=2):
super(parent,self).__init__(x,y)
self.var1=x
self.var2=y
class parent2(Base):
var4=11
var5=12
def __init__(self,x=3,y=4):
super(parent2,self).__init__(x,y)
self.var4=x
self.var5=y
def parprint(self):
print self.var4
print self.var5
class child(parent, parent2):
var3=5
def __init__(self,x,y):
super(child, self).__init__(x,y)
childobject = child(9,10)
print childobject.var1
print childobject.var2
print childobject.var3
childobject.parprint()
Es posible que se pregunte: "¿Por qué usar Base
?". Si parent
y parent2
han heredado directamente del object
, entonces super(parent2,self).__init__(x,y)
llamaría al object.__init__(x,y)
. Eso genera un TypeError
ya que el object.__init__()
no toma parámetros.
Para solucionar este problema, puede crear una Base
clase que acepte argumentos para __init__
pero no los pase al object.__init__
. Con parent
y parent2
heredando de Base
, evita el TypeError
.