¿Cómo funciona la herencia múltiple con los argumentos super () y diferentes __init __ ()?

Solo estoy sumergiéndome en algunos temas más avanzados de python (bueno, avanzado para mí al menos). Ahora estoy leyendo acerca de la herencia múltiple y cómo puedes usar super (). Más o menos entiendo la forma en que se usa la función super, pero (1) ¿Qué tiene de malo hacerlo de esta manera ?

class First(object): def __init__(self): print "first" class Second(object): def __init__(self): print "second" class Third(First, Second): def __init__(self): First.__init__(self) Second.__init__(self) print "that's it" 

En el super (), el artículo de Andrew Kuchlings sobre Python Warts dice:

el uso de super () también será correcto cuando la clase Derivada herede de varias clases base y algunas o todas tienen métodos de inicio

Así que reescribí el ejemplo anterior de la siguiente manera:

 class First(object): def __init__(self): print "first" class Second(object): def __init__(self): print "second" class Third(First, Second): def __init__(self): super(Third, self).__init__(self) print "that's it" 

Sin embargo, esto solo ejecuta el primer inicio que puede encontrar, que está en First . (2) ¿Se puede usar super() para ejecutar tanto los inicios del First y el Second , y si es así, cómo? Ejecutar super(Third, self).__init__(self) dos veces solo se ejecuta Primero. init () dos veces ..

Para añadir un poco más de confusión. ¿Qué pasa si las funciones init () de las clases heredadas toman argumentos diferentes? Por ejemplo, que tal si tuviera algo como esto:

 class First(object): def __init__(self, x): print "first" class Second(object): def __init__(self, y, z): print "second" class Third(First, Second): def __init__(self, x, y, z): First.__init__(self, x) Second.__init__(self, y, z) print "that's it" 

(3) ¿Cómo podría proporcionar los argumentos relevantes a las diferentes funciones heredadas de las clases init utilizando super ()?

Todos los consejos son bienvenidos!

PD. Como tengo varias preguntas las hice en negrita y las numeré.

Para la pregunta 2, debe llamar super en cada clase:

 class First(object): def __init__(self): super(First, self).__init__() print "first" class Second(object): def __init__(self): super(Second, self).__init__() print "second" class Third(First, Second): def __init__(self): super(Third, self).__init__() print "that's it" 

Para la pregunta 3, eso no se puede hacer, su método debe tener la misma firma. Pero podría ignorar algunos parámetros en las clases principales o usar argumentos de palabras clave.

1) No hay nada de malo en hacer lo que has hecho en 1, si quieres usar los atributos de la clase base, debes llamar a la clase base init () o incluso si estás usando métodos de la clase base que usa los atributos. de su propia clase, entonces tienes que llamar a baseclass init ()

2) No se puede usar super para ejecutar tanto el inicio como el primero, ya que Python usa MRO (orden de resolución de métodos)

ver el siguiente código esto es jerarquía de diamante

 class A(object): def __init__(self): self.a = 'a' print self.a class B(A): def __init__(self): self.b = 'b' print self.b class C(A): def __init__(self): self.c = 'c' print self.c class D(B,C): def __init__(self): self.d = 'd' print self.d super(D, self).__init__() d = D() print D.mro() 

Se imprime:

 d b [, , , , ] 

MRO de python sería D, B, C, A

Si B no tiene el método init, va por C.

3) No puedes hacerlo, todos los métodos deben tener la misma firma.