11.1 Method Resolution Order
L'Ordre de Résolution des Méthodes (Method Resolution Order, MRO) détermine la séquence dans laquelle Python recherche les méthodes et attributs dans la hiérarchie des classes. C'est particulièrement important quand on travaille avec l'héritage multiple, où une classe peut hériter des attributs et méthodes de plusieurs classes parent.
En gros, il y a un ordre fixe strict (ou plutôt un algorithme), selon lequel Python parcourt l'arbre d'héritage des classes. Cet algorithme assure l'ordre correct de recherche des méthodes, qui peut être décrit comme suit :
Algorithme de C3-linearisation
L'algorithme de C3-linearisation détermine le MRO en combinant :
- La classe elle-même.
- La liste des classes parent dans l'ordre où elles sont mentionnées.
- MRO des classes parent dans le même ordre.
Règles de l'algorithme de C3-linearisation
- Conserver l'ordre local des méthodes : si la classe
Aest mentionnée avant la classeB, toutes les méthodes de la classeAdoivent être considérées avant les méthodes de la classeB. - Respecter l'ordre dans les classes parent : si la classe
Aest un parent de la classeB, alors toutes les méthodes de la classeAdoivent être considérées avant les méthodes de la classeB. - Considérer l'ordre d'héritage : si la classe
Cest un parent pour deux ou plusieurs classes, l'ordre des méthodes de la classeCdoit être maintenu dans le MRO de toutes ces classes.
Étapes de l'algorithme :
Étape 1. Commencer par la classe elle-même :
On commence toujours par la classe elle-même où la méthode est appelée.
Étape 2. Ajouter les classes de base dans l'ordre où elles sont mentionnées :
Après la classe courante, vérifier les classes de base dans l'ordre où elles sont mentionnées lors de l'héritage.
Étape 3. Parcourir les classes parent :
Rechercher les attributs et méthodes là-bas.
Étape 4. Combiner le MRO des classes parent :
Si la même classe de base est héritée à travers plusieurs chemins, elle est vérifiée une seule fois et dans le bon ordre (toutes les autres fois elle sera ignorée).
Pour ceux qui sont déjà familiers avec "Algorithmes et structures de données", c'est une recherche en profondeur plutôt qu'en largeur.
11.2 Vérification du MRO
En Python, on peut vérifier l'ordre de recherche des méthodes et attributs d'une classe, en utilisant l'attribut __mro__ ou la fonction mro().
Exemple :
class A:
def method(self):
print("A")
class B(A):
def method(self):
print("B")
class C(A):
def method(self):
print("C")
class D(B, C):
def method(self):
print("D")
# Vérification du MRO
print(D.__mro__)
La sortie sera :
(<class '__main__.D'>,
<class '__main__.B'>,
<class '__main__.C'>,
<class '__main__.A'>,
<class 'object'>)
Cela montre l'ordre dans lequel Python va rechercher les méthodes et attributs :
D: Python vérifie d'abord la méthode dans la classeD.-
B: Ensuite, Python vérifie la méthode dans la classeB(le premier parent). -
C: Si la méthode n'est pas trouvée dans la classeB, Python vérifie la méthode dans la classeC(le second parent). -
A: Si la méthode n'est pas trouvée dans les classesBetC, Python vérifie la méthode dans la classeA. -
object: Enfin, Python vérifie la méthode dans la classe de baseobject.
11.3 Utilisation de super() avec MRO
La fonction super() suit le MRO pour appeler les méthodes des classes parent dans le bon ordre. Voyons un exemple d'utilisation de
super():
class A:
def method(self):
print("A")
super().method()
class B(A):
def method(self):
print("B")
super().method()
class C(A):
def method(self):
print("C")
super().method()
class D(B, C):
def method(self):
print("D")
super().method()
d = D()
d.method()
La sortie sera la suivante :
D
B
C
A
Ordre de recherche (MRO)
1. Appel de la méthode method de la classe D :
- Python vérifie d'abord la méthode dans la classe
Det la trouve là. - La méthode
D.method()s'exécute et imprime"D". - Ensuite,
super().method()est appelé, suivant le MRO pour appeler la méthode suivante.
2. Appel de la méthode method de la classe B :
- Selon le MRO, la classe suivante après
DestB. - La méthode
B.method()s'exécute et imprime"B". - Ensuite,
super().method()est appelé, suivant le MRO pour appeler la méthode suivante.
3. Appel de la méthode method de la classe C :
- La classe suivante dans le MRO après
BestC. - La méthode
C.method()s'exécute et imprime"C". - Ensuite,
super().method()est appelé, suivant le MRO pour appeler la méthode suivante.
4. Appel de la méthode method de la classe A :
- La classe suivante dans le MRO après
CestA. - La méthode
A.method()s'exécute et imprime"A". - Ensuite,
super().method()est appelé, mais commeAn'a pas de méthodes parentmethod(à partobject), l'appel se termine sans autres actions.
GO TO FULL VERSION