Ceci est détaillé avec une quantité raisonnable de détails par Guido lui-même dans son article de blog Method Resolution Order (y compris deux tentatives antérieures).
Dans votre exemple, Third()
va appeler First.__init__
. Python recherche chaque attribut dans les parents de la classe car ils sont répertoriés de gauche à droite. Dans ce cas, nous recherchons __init__
. Donc, si vous définissez
class Third(First, Second):
...
Python commencera par regarder First
, et, s'il First
n'a pas l'attribut, alors il regardera Second
.
Cette situation devient plus complexe lorsque l'héritage commence à croiser les chemins (par exemple s'il est First
hérité de Second
). Lisez le lien ci-dessus pour plus de détails, mais, en un mot, Python essaiera de maintenir l'ordre dans lequel chaque classe apparaît dans la liste d'héritage, en commençant par la classe enfant elle-même.
Ainsi, par exemple, si vous aviez:
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"
le MRO serait [Fourth, Second, Third, First].
Soit dit en passant: si Python ne peut pas trouver un ordre de résolution de méthode cohérent, il lèvera une exception, au lieu de retomber sur un comportement qui pourrait surprendre l'utilisateur.
Modifié pour ajouter un exemple de MRO ambigu:
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"
Devrait Third
être MRO » [First, Second]
ou [Second, First]
? Il n'y a aucune attente évidente et Python générera une erreur:
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution order (MRO) for bases Second, First
Edit: Je vois plusieurs personnes affirmer que les exemples ci-dessus manquent d' super()
appels, alors laissez-moi vous expliquer: le but des exemples est de montrer comment le MRO est construit. Ils ne sont pas destinés à imprimer "premier \ nsecond \ tiers" ou autre. Vous pouvez - et devriez, bien sûr, jouer avec l'exemple, ajouter des super()
appels, voir ce qui se passe et acquérir une compréhension plus approfondie du modèle d'héritage de Python. Mais mon objectif ici est de rester simple et de montrer comment le MRO est construit. Et il est construit comme je l'ai expliqué:
>>> Fourth.__mro__
(<class '__main__.Fourth'>,
<class '__main__.Second'>, <class '__main__.Third'>,
<class '__main__.First'>,
<type 'object'>)
super()
est utile. Je ne recommanderais pas de l'utiliser avec des classes utilisant l'héritage linéaire, où c'est juste une surcharge inutile.