Qu'est-ce que le MRO ?
En Python, le MRO (Method Resolution Order, ou ordre de résolution des méthodes) indique dans quel ordre le langage parcourt les classes pour trouver une méthode ou un attribut.
C'est un concept particulièrement parlant lorsqu'on utilise l'héritage multiple. C'est grâce au MRO que Python sait exactement quelle méthode exécuter s'il existe des conflits ou des méthodes du même nom dans les classes parentes.
Depuis Python 2.3, l’algorithme utilisé par le MRO s'appelle la linéarisation C3. Ainsi, le comportement du MRO est prévisible : Python cherchera toujours de la classe enfant vers les parents, de la gauche vers la droite.
Comment afficher le MRO ?
Python permet d'afficher l'ordre de résolution d'une classe de deux manières très simples :
-
L'attribut spécial
__mro__qui retourne un tuple -
La méthode
mro()qui retourne une liste
Le diamant
class A: def parler(self): print("Je suis la classe A") class B(A): def parler(self): print("Je suis la classe B") class C(A): def parler(self): print("Je suis la classe C") # D hérite de B et C (de gauche à droite) class D(B, C): pass # Création d'une instance de D mon_objet = D() mon_objet.parler() # Affiche : Je suis la classe B # Affichage du MRO print(D.__mro__) # Résultat : (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
-
Python cherche d'abord la méthode
parler()dansDsans la trouver -
Il cherche ensuite dans le premier parent (à gauche),
B -
Il la trouve dans
Bet l'exécute
Si la méthode n'avait pas été dans B, il aurait continué dans C, et ainsi de suite.
Quand le MRO échoue avec une TypeError
Afin d'éviter les comportements imprévisibles, l'algorithme est strict. Si vous créez une hiérarchie illogique, Python refusera de créer la classe et lèvera une erreur.
class A: def parler(self): print("Je suis la classe A") class B(A): def parler(self): print("Je suis la classe B") # Erreur ! On demande de lire A avant B, alors que B hérite déjà de A class C(A, B): def parler(self): print("Je suis la classe C")
Vous obtiendrez une exception au moment de la définition de C : TypeError: Cannot create a consistent method resolution order (MRO) for bases A, B.
Attention
L'algorithme C3 impose qu'une classe enfant (B) soit toujours parcourue avant sa classe parente (A). En déclarant class C(A, B), nous demandons à Python de parcourir A avant B, ce qui est contradictoire car B hérite de A.
Il est utile de comprendre le MRO pour bien assimiler le fonctionnement de la fonction super(), qui s'appuie sur le MRO pour les appels aux méthodes des classes parentes. De plus, la création de mixins est une pratique courante en Python (notamment dans les frameworks comme Django), et le MRO garantit que les fonctionnalités injectées via ces mixins s'ajoutent dans le bon ordre.