Python multi-herencia, __init__

Con respecto a la herencia múltiple, 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 

Si desea usar super en child para llamar parent.__init__ y parent2._init__ , entonces ambos parent __init__ s también deben llamar 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__ causada 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() 

Quizás se esté preguntando, “¿Por qué usar Base ?”. Si parent y parent2 habían heredado directamente del object , super(parent2,self).__init__(x,y) llamaría 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 .

Debido a que parent es el siguiente en el orden de resolución de métodos (MRO) , y nunca usa super() para llamar a parent2 .

Vea 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 [, , , , ] 

La herencia múltiple de Python es como una cadena, en Child class mro , la super clase 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, produciendo:

 Child called by Construct ParentA called by Child Base called by ParentA [, , , , ] 

Más información sobre MRO