logo

Ordre de résolution des méthodes en Python

Dans ce didacticiel, nous découvrirons l'ordre de résolution des méthodes, également connu sous le nom de MRO. C'est un concept essentiel de l'héritage Python.

L'ordre de résolution des méthodes décrit le chemin de recherche de la classe qui Python utilise pour obtenir la méthode appropriée dans les classes qui contiennent le multi-héritage.

Introduction

Comme nous le savons, une classe héritée est appelée sous-classe ou classe parent, tandis que la classe qui hérite est appelée classe enfant ou sous-classe. Dans le multi-héritage, une classe peut être composée de nombreuses fonctions, donc la technique de l'ordre de résolution des méthodes est utilisée pour rechercher l'ordre dans lequel la classe de base est exécutée.

En termes simples : « La méthode ou les attributs sont explorés dans la classe actuelle, si la méthode n'est pas présente dans la classe actuelle, la recherche est déplacée vers les classes parentes, et ainsi de suite ». Ceci est un exemple de recherche approfondie.

Il joue un rôle essentiel dans l’héritage multiple où la même méthode peut être retrouvée dans plusieurs superclasses.

Pour mieux le comprendre, voyons comment nous pouvons l'utiliser.

Exemple -

 class A: def myname(self): print('I am a class A') class B(A): def myname(self): print('I am a class B') class C(A): def myname(self): print('I am a class C') c = C() print(c.myname()) 

Sortir:

 I am a class C 

Explication -

Il existe un héritage multiple dans le code ci-dessus. Nous avons défini trois classes appelées A, B et C, et ces classes ont le même nom de méthode appelée mon nom(). Nous avons créé une classe d'objet C. L'objet a invoqué la classe C, pas la classe, tandis que la classe C a hérité de la méthode de la classe A.

L'ordre est suivi dans le code ci-dessus est classe B -> classe A. Cette technique est connue sous le nom de MRO (Method Resolution Order).

Comprenons un autre exemple d'héritage multiple.

Exemple -

 class A: def myname(self): print(' I am a class A') class B(A): def myname(self): print(' I am a class B') class C(A): def myname(self): print('I am a class C') # classes ordering class D(B, C): pass d = D() d.myname() 

Sortir:

 I am a class B 

Explication -

Dans le code ci-dessus, nous avons créé une autre classe D sans définir les attributs de classe qui ont hérité des classes B et C. Quand nous avons invoqué la méthode mon nom(), il va en classe D et recherche le mon nom( ) fonction. Mais la classe D n'a aucune déclaration. Par conséquent, la recherche passe à la classe B et obtient le mon nom() fonction et renvoie le résultat. La recherche se déroulera comme suit.

 Class D -> Class B -> Class C -> Class A 

Si la classe B n’a pas de méthode, elle invoquera la méthode de la classe C.

Ici, nous vous suggérons de supprimer la méthode de classe B et de vérifier ce qui se passe. En faisant cela, vous aurez une idée du fonctionnement de la méthode de résolution.

Ordre de style ancien et nouveau

Dans l'ancienne version de Python (2.1), nous sommes limités à l'utilisation des anciennes classes mais Python (2.2 & suite), nous pouvons utiliser les nouvelles classes. Par défaut, Python 3 a des (nouvelles) classes originales. Le premier parent de la nouvelle classe de style hérite de la classe « objet » racine de Python. Voyons l'exemple suivant -

Exemple -

 # Old style class class OldStyleClass: pass # New style class class NewStyleClass(object): pass 

Le style de déclaration des deux classes est différent. Dans la résolution de la méthode, les classes de style ancien suivent l'algorithme de profondeur d'abord de gauche à droite (DLR), tandis que les classes de nouveau style utilisent l'algorithme de linéarisation C3 tout en effectuant un héritage multiple.

DLR Algorithm

Python crée une liste de classes tout en implémentant l'héritage multiple entre les classes. Cette liste est utilisée pour déterminer quelle méthode doit être appelée et qui est invoquée par les instances.

Nous pouvons supposer que travailler par son nom car la résolution de la méthode recherchera d'abord en profondeur, puis ira de gauche à droite. Ci-dessous l'exemple.

Exemple -

 class A: pass class B: pass class C(A, B): pass class D(B, A): pass class E(C,D): pass 

Tout d’abord, l’algorithme recherchera dans la classe d’instance la méthode invoquée. S'il n'est pas trouvé, il va aux premiers parents, s'il n'est pas non plus trouvé. Il examinera le parent du parent. Cela continuera jusqu'à la fin de l'héritage des classes.

Dans l'exemple ci-dessus, l'ordre de résolution de la méthode sera :

 class D -> class B -> class A -> class C -> class A 

Mais A ne peut pas être présent deux fois donc -

 class D -> class B -> class A -> class C -> 

Cet algorithme montre le comportement étrange à l'époque. Voyons l'exemple ci-dessous.

convertir une chaîne en json en java

Exemple -

 class A: pass class B: pass class C(A, B): pass class D(B, A): pass class E(C,D): pass 

Selon l'algorithme DLR, l'ordre sera E, C, D, B, A. Il y a l'échange des classes A et B dans la classe C, ce qui est très ambigu. Cela signifie que l'algorithme ne préserve pas la propriété de monotonie.

Samuele Perdoni a été la première personne à découvrir une incohérence entre les algorithmes MRO.

Algorithme de linéarisation C3

L'algorithme de linéarisation C3 est une meilleure version de l'algorithme DLR car il supprime l'incohérence. Cet algorithme comporte certaines restrictions indiquées ci-dessous.

  • Les enfants doivent précéder leurs parents.
  • Si une classe particulière hérite d'une ou plusieurs classes, elles sont enregistrées dans l'ordre spécifié dans le tuple de la classe de base.

Règles de l'algorithme de linéarisation C3

  • La structure de l'ordre de résolution des méthodes est définie par le graphe d'héritage.
  • L'utilisateur doit visiter la super classe uniquement après avoir visité les méthodes des classes locales.
  • Préserver la monotonie

Méthode pour la classe de résolution de méthode

Python propose deux façons d'obtenir l'ordre de résolution des méthodes d'une classe : __mro__ attribut ou mro() méthode. A l’aide de ces méthodes, nous pouvons afficher l’ordre de méthode dans lequel elles sont résolues.

Comprenons l'exemple suivant.

Exemple -

 class A: def myname(self): print(' I am a class A') class B(A): def myname(self): print(' I am a class B') class C(A): def myname(self): print('I am a class C') # classes ordering class D(B, C): pass # it prints the lookup order print(D.__mro__) print(C.mro()) 

Sortir:

 (, , , , ) [, , ] 

Comme nous pouvons le voir dans le résultat ci-dessus, nous obtenons l’ordre de résolution de la méthode. De cette manière, l’algorithme de linéarisation C3 fonctionne pour l’héritage multiple.