logo

Ordre de resolució de mètodes en Python

En aquest tutorial, coneixerem l'ordre de resolució del mètode, que també es coneix com MRO. És un concepte essencial de l'herència de Python.

L'ordre de resolució del mètode descriu la ruta de cerca de la classe que Python utilitza per obtenir el mètode adequat a les classes que contenen l'herència múltiple.

Introducció

Com ho sabem, una classe que s'hereta s'anomena subclasse o classe pare, mentre que la classe que hereta es coneix com a classe o subclasse fill. En l'herència múltiple, una classe pot constar de moltes funcions, de manera que la tècnica d'ordre de resolució del mètode s'utilitza per cercar l'ordre en què s'executa la classe base.

En paraules senzilles: 'El mètode o els atributs s'exploren a la classe actual, si el mètode no està present a la classe actual, la cerca es mou a les classes pares, etc.'. Aquest és un exemple de cerca en profunditat.

Té un paper essencial en l'herència múltiple on el mateix mètode es pot trobar a les múltiples superclasses.

Per entendre-ho millor, veiem com podem utilitzar-lo.

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()) 

Sortida:

caràcter d'escapament de java
 I am a class C 

Explicació -

Hi ha una herència múltiple al codi anterior. Hem definit tres classes anomenades A, B i C, i aquestes classes tenen el mateix nom anomenat mètode el meu nom(). Vam crear una classe d'objectes C. L'objecte va invocar la classe C, no la classe, mentre que la classe C va heretar el mètode de la classe A.

L'ordre es segueix al codi anterior classe B -> classe A. Aquesta tècnica es coneix com MRO (métode ordre de resolució).

llista ordenar per java

Entenem un altre exemple d'herència múltiple.

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() 

Sortida:

 I am a class B 

Explicació -

Al codi anterior, hem creat una altra classe D sense definir els atributs de classe que heretaven les classes B i C. Quan vam invocar el mètode el meu nom(), va a la classe D i cerca el el meu nom( ) funció. Però la classe D no té cap declaració. Per tant, la cerca es transfereix a la classe B, obté el el meu nom() funció i retorna el resultat. La recerca es farà de la següent manera.

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

Si la classe B no tingués un mètode, invocarà el mètode de la classe C.

Aquí, us suggerim que elimineu el mètode de classe B i comproveu què passa. En fer això, tindreu una idea de com funciona la resolució del mètode.

Ordre d'estil antic i nou

A la versió anterior de Python (2.1), estem restringits a utilitzar les classes antigues però Python (2.2 i continua), podem utilitzar les noves classes. Per defecte, Python 3 té classes originals (nous). El primer pare de la nova classe d'estil hereta de la classe 'objecte' arrel de Python. Vegem el següent exemple -

Exemple -

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

L'estil de declaració d'ambdues classes és diferent. En la resolució del mètode, les classes d'estil antic segueixen l'algorisme de la profunditat primer de l'esquerra a la dreta (DLR), mentre que les classes d'estil noves utilitzen l'algorisme de linealització C3 mentre realitzen una herència múltiple.

Algoritme DLR

Python crea una llista de classes mentre implementa l'herència múltiple entre les classes. Aquesta llista s'utilitza per determinar quin mètode s'ha d'anomenar, i és invocat per les instàncies.

gimp substitueix el color

Podem suposar que treballant pel seu nom ja que la resolució del mètode cercarà primer la profunditat i després anirà d'esquerra a dreta. A continuació es mostra l'exemple.

Exemple -

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

En primer lloc, l'algoritme cercarà a la classe d'instància el mètode invocat. Si no es troba, passa als primers pares, si tampoc es troba. Mirarà el pare del pare. Això continuarà fins al final de l'herència de les classes.

A l'exemple anterior, l'ordre de resolució del mètode serà -

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

Però, A no pot estar dues vegades present, així que...

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

Aquest algorisme mostra el comportament estrany en aquell moment. Vegem l'exemple següent.

Exemple -

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

Segons l'algoritme DLR, l'ordre serà E, C, D, B, A. Hi ha l'intercanvi de classes A i B a la classe C, que és molt ambigu. Significa que l'algoritme no conserva la propietat de monotonia.

Samuele Perdoni va ser la primera persona que va descobrir una inconsistència entre els algorismes MRO.

C3 Algorisme de linealització

L'algoritme de linealització C3 és una millor versió de l'algoritme DLR perquè elimina la inconsistència. Aquest algorisme té algunes restriccions que es donen a continuació.

  • Els nens han de precedir els seus pares.
  • Si una classe particular hereta d'una o més classes, es desaran en l'ordre especificat a la tupla de la classe base.

Regles de l'algoritme de linealització C3

  • L'estructura de l'ordre de resolució del mètode es defineix pel gràfic d'herència.
  • L'usuari ha de visitar la superclasse només després de visitar els mètodes de les classes locals.
  • Preservar la monotonia

Mètode per a la classe de resolució del mètode

Python proporciona dues maneres d'obtenir l'ordre de resolució del mètode d'una classe: __mro__ atribut o mro() mètode. Amb l'ajuda d'aquests mètodes, podem mostrar l'ordre del mètode en què es resolen.

Entenem l'exemple següent.

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()) 

Sortida:

arquitectura d'arrencada de primavera
 (, , , , ) [, , ] 

Com podem veure a la sortida anterior, obtenim l'ordre de resolució del mètode. D'aquesta manera, l'algoritme de linealització C3 funciona per a l'herència múltiple.