logo

Methode Resolutie Volgorde in Python

In deze zelfstudie leren we over de volgorde van de methoderesolutie, ook wel de MRO genoemd. Het is een essentieel concept van Python-overerving.

De methoderesolutievolgorde beschrijft het zoekpad van de klasse die Python gebruikt om de juiste methode te verkrijgen in klassen die de multi-overerving bevatten.

Invoering

Zoals we weten, wordt een klasse die wordt geërfd de Subklasse of Parent-klasse genoemd, terwijl de klasse die erft bekend staat als een onderliggende klasse of subklasse. Bij multi-overerving kan een klasse uit veel functies bestaan, dus wordt de methode-resolutie-volgordetechniek gebruikt om de volgorde te doorzoeken waarin de basisklasse wordt uitgevoerd.

In eenvoudige bewoordingen: 'De methode of attributen worden onderzocht in de huidige klasse, als de methode niet aanwezig is in de huidige klasse, wordt de zoekopdracht verplaatst naar de bovenliggende klassen, enzovoort'. Dit is een voorbeeld van een diepte-eerst-zoekopdracht.

Het speelt een essentiële rol bij meervoudige overerving waarbij dezelfde methode kan worden gevonden in meerdere superklassen.

Laten we, om het beter te begrijpen, kijken hoe we het kunnen gebruiken.

Voorbeeld -

tekenreeks splitsen c++
 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()) 

Uitgang:

 I am a class C 

Uitleg -

Er is een meervoudige overerving in de bovenstaande code. We hebben drie klassen gedefinieerd, genaamd A, B en C, en deze klassen hebben dezelfde naam: methode mijn naam(). We hebben een objectklasse C gemaakt. Het object riep klasse C aan, niet de klasse, terwijl klasse C de klasse A-methode erfde.

De volgorde wordt gevolgd in de bovenstaande code klasse B -> klasse A. Deze techniek staat bekend als MRO (methoderesolutievolgorde).

Laten we een ander voorbeeld van meervoudige overerving begrijpen.

Voorbeeld -

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

Uitgang:

 I am a class B 

Uitleg -

In de bovenstaande code hebben we nog een D-klasse gemaakt zonder klasse-attributen te definiëren die de B- en C-klasse overerven. Toen we de methode aanroepen mijn naam(), het gaat naar klasse D en zoekt naar de mijn naam( ) functie. Maar klasse D heeft geen enkele verklaring. Daarom wordt de zoekopdracht overgedragen naar klasse B en krijgt de mijn naam() functie en retourneert het resultaat. De zoektocht zal als volgt plaatsvinden.

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

Als klasse B geen methode zou hebben, zal deze de klasse C-methode aanroepen.

Hier stellen we voor dat u de klasse B-methode verwijdert en controleert wat er gebeurt. Door dit te doen, krijgt u een idee van hoe de methoderesolutie werkt.

Orde van oude en nieuwe stijl

In de oudere versie van Python (2.1) zijn we beperkt tot het gebruik van de oude klassen, maar Python (2.2 & verder), kunnen we de nieuwe klassen gebruiken. Standaard heeft Python 3 originele (nieuwe) klassen. De eerste ouder van de nieuwe stijlklasse erft van Python root 'object'-klasse. Laten we het volgende voorbeeld bekijken -

verschil tussen liefde en like

Voorbeeld -

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

De declaratiestijl van beide klassen is verschillend. Bij de methoderesolutie volgen klassen in oude stijl het diepte-eerst van links naar rechts-algoritme (DLR), terwijl klassen in nieuwe stijl het C3-linearisatie-algoritme gebruiken terwijl ze meervoudige overerving uitvoeren.

DLR-algoritme

Python maakt een lijst met klassen terwijl de meervoudige overerving tussen de klassen wordt geïmplementeerd. Die lijst wordt gebruikt om te bepalen welke methode moet worden aangeroepen als deze door instances wordt aangeroepen.

We kunnen ervan uitgaan dat we met de naam werken, aangezien de methoderesolutie eerst de diepte doorzoekt en dan van links naar rechts gaat. Hieronder vindt u het voorbeeld.

Voorbeeld -

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

Eerst zal het algoritme in de instanceklasse zoeken naar de aangeroepen methode. Indien niet gevonden gaat het naar de eerste ouders, indien er ook niet gevonden wordt. Er wordt gekeken naar de ouder van de ouder. Dit zal doorgaan tot het einde van de ervende klassen.

In het bovenstaande voorbeeld is de volgorde van de methoderesolutie:

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

Maar A kan niet tweemaal aanwezig zijn, dus -

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

Dit algoritme laat het vreemde gedrag van dat moment zien. Laten we het onderstaande voorbeeld bekijken.

Voorbeeld -

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

Volgens het DLR-algoritme is de volgorde E, C, D, B, A. Er is een uitwisseling van klassen A en B in klasse C, wat zeer dubbelzinnig is. Het betekent dat het algoritme de monotoniciteitseigenschap niet behoudt.

Samuele Perdoni was de eerste persoon die een inconsistentie tussen de MRO-algoritmen ontdekte.

C3 Linearisatie-algoritme

Het C3-linearisatiealgoritme is een betere versie van het DLR-algoritme omdat het de inconsistentie wegneemt. Dit algoritme heeft enkele beperkingen die hieronder worden gegeven.

  • Kinderen moeten hun ouders voorgaan.
  • Als een bepaalde klasse erft van een of meer klassen, worden deze opgeslagen in de volgorde die is opgegeven in het tupel van de basisklasse.

Regels van het C3-linearisatiealgoritme

  • De structuur van de methoderesolutievolgorde wordt gedefinieerd door de overervingsgrafiek.
  • De gebruiker mag de superklasse pas bezoeken nadat de methoden van de lokale klassen zijn bezocht.
  • Behoud de monotoniciteit

Methode voor methoderesolutieklasse

Python biedt twee manieren om de methoderesolutievolgorde van een klasse te verkrijgen: __mro__ attribuut of mro() methode. Met behulp van deze methoden kunnen we de volgorde weergeven van de methode waarin ze zijn opgelost.

Laten we het volgende voorbeeld begrijpen.

Voorbeeld -

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

Uitgang:

 (, , , , ) [, , ] 

Zoals we in de bovenstaande uitvoer kunnen zien, krijgen we de volgorde van de resolutievolgorde van de methode. Op deze manier werkt het C3-linearisatie-algoritme voor meervoudige overerving.