Esto se detalla con una cantidad razonable de detalles por el propio Guido en su publicación de blog Método Resolución Orden (incluidos dos intentos anteriores).
En su ejemplo, Third()
llamará First.__init__
. Python busca cada atributo en los padres de la clase, ya que se enumeran de izquierda a derecha. En este caso, lo estamos buscando __init__
. Entonces, si define
class Third(First, Second):
...
Python comenzará mirando First
y, si First
no tiene el atributo, veráSecond
.
Esta situación se vuelve más compleja cuando la herencia comienza a cruzarse (por ejemplo, si se First
hereda deSecond
). Lea el enlace de arriba para obtener más detalles, pero, en pocas palabras, Python intentará mantener el orden en el que cada clase aparece en la lista de herencia, comenzando con la clase secundaria.
Entonces, por ejemplo, si tuvieras:
class First(object):
def __init__(self):
print "first"
class Second(First):
def __init__(self):
print "second"
class Third(First):
def __init__(self):
print "third"
class Fourth(Second, Third):
def __init__(self):
super(Fourth, self).__init__()
print "that's it"
el MRO sería [Fourth, Second, Third, First].
Por cierto: si Python no puede encontrar un orden de resolución de método coherente, generará una excepción, en lugar de recurrir al comportamiento que podría sorprender al usuario.
Editado para agregar un ejemplo de un MRO ambiguo:
class First(object):
def __init__(self):
print "first"
class Second(First):
def __init__(self):
print "second"
class Third(First, Second):
def __init__(self):
print "third"
¿Debería Third
ser MRO [First, Second]
o [Second, First]
? No hay expectativas obvias, y Python generará un error:
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution order (MRO) for bases Second, First
Editar: veo a varias personas argumentando que los ejemplos anteriores carecen de super()
llamadas, así que permítanme explicar: El objetivo de los ejemplos es mostrar cómo se construye el MRO. Están no destinados a imprimir "primero \ Nsecond \ tercera" o lo que sea. Puede, y debe, por supuesto, jugar con el ejemplo, agregar super()
llamadas, ver qué sucede y obtener una comprensión más profunda del modelo de herencia de Python. Pero mi objetivo aquí es mantenerlo simple y mostrar cómo se construye el MRO. Y está construido como lo expliqué:
>>> Fourth.__mro__
(<class '__main__.Fourth'>,
<class '__main__.Second'>, <class '__main__.Third'>,
<class '__main__.First'>,
<type 'object'>)
super()
es útil. No recomendaría usarlo con clases que usen herencia lineal, donde es una sobrecarga inútil.