Isso é detalhado com uma quantidade razoável de detalhes pelo próprio Guido em sua postagem no blog Ordem de resolução de métodos (incluindo duas tentativas anteriores).
No seu exemplo, Third()
ligará First.__init__
. O Python procura cada atributo nos pais da classe, conforme listados da esquerda para a direita. Neste caso, estamos procurando __init__
. Então, se você definir
class Third(First, Second):
...
O Python começará examinando First
e, se First
não tiver o atributo, será analisado Second
.
Essa situação se torna mais complexa quando a herança começa a cruzar caminhos (por exemplo, se First
herdada de Second
). Leia o link acima para obter mais detalhes, mas, em poucas palavras, o Python tentará manter a ordem em que cada classe aparece na lista de herança, começando com a própria classe filho.
Então, por exemplo, se você tivesse:
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"
o MRO seria [Fourth, Second, Third, First].
A propósito: se o Python não conseguir encontrar uma ordem de resolução de método coerente, isso criará uma exceção, em vez de voltar ao comportamento que pode surpreender o usuário.
Editado para adicionar um exemplo de uma MRO ambígua:
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"
O Third
MRO deve ser [First, Second]
ou [Second, First]
? Não há expectativa óbvia, e o Python gerará um erro:
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution order (MRO) for bases Second, First
Edit: Eu vejo várias pessoas argumentando que os exemplos acima não têm super()
chamadas, então deixe-me explicar: O objetivo dos exemplos é mostrar como o MRO é construído. Eles não pretendem imprimir "primeiro \ nsegundo \ terceiro" ou o que for. Você pode - e deve, é claro, brincar com o exemplo, adicionar super()
chamadas, ver o que acontece e obter uma compreensão mais profunda do modelo de herança do Python. Mas meu objetivo aqui é simplificar e mostrar como o MRO é construído. E é construído como expliquei:
>>> Fourth.__mro__
(<class '__main__.Fourth'>,
<class '__main__.Second'>, <class '__main__.Third'>,
<class '__main__.First'>,
<type 'object'>)
super()
é útil. Eu não recomendaria usá-lo com classes usando herança linear, onde é apenas uma sobrecarga inútil.