logo

Menetelmän resoluutiojärjestys Pythonissa

Tässä opetusohjelmassa opimme menetelmän resoluutiojärjestyksestä, joka tunnetaan myös nimellä MRO. Se on olennainen Python-perinnön käsite.

Metodin ratkaisujärjestys kuvaa luokan, joka Python käyttää saadakseen sopivan menetelmän luokissa, jotka sisältävät moniperinnön.

Johdanto

Kuten tiedämme, luokkaa, jota peritään, kutsutaan alaluokiksi tai yläluokiksi, kun taas luokkaa, joka perii, kutsutaan alaluokkaksi tai alaluokiksi. Moniperinnössä luokka voi koostua useista funktioista, joten metodiresoluutiojärjestystekniikkaa käytetään etsimään järjestystä, jossa perusluokka suoritetaan.

Yksinkertaisesti sanottuna - 'Metodia tai attribuutteja tutkitaan nykyisessä luokassa, jos menetelmää ei ole nykyisessä luokassa, haku siirtyy pääluokkiin ja niin edelleen'. Tämä on esimerkki syvällisestä hausta.

Sillä on olennainen rooli moniperinnössä, jossa sama menetelmä löytyy useista superluokista.

Ymmärtääksemme sen paremmin, katsotaanpa, kuinka voimme käyttää sitä.

Esimerkki -

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

Lähtö:

 I am a class C 

Selitys -

kaupunki Yhdysvalloissa

Yllä olevassa koodissa on moninkertainen perintö. Olemme määrittäneet kolme luokkaa nimeltä A, B ja C, ja näillä luokilla on samanniminen menetelmä nimeltä nimeni(). Loimme olioluokan C. Objekti kutsui luokkaa C, ei luokkaa, kun taas luokka C peri luokan A menetelmän.

Järjestystä noudatetaan yllä olevassa koodissa luokka B -> luokka A. Tämä tekniikka tunnetaan nimellä MRO (method resolution order).

Ymmärretään toinen esimerkki moniperinnöstä.

Yhdistä lajittelu

Esimerkki -

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

Lähtö:

 I am a class B 

Selitys -

Yllä olevassa koodissa olemme luoneet toisen D-luokan määrittelemättä luokkaattribuutteja, jotka perivät B- ja C-luokan. Kun käytimme menetelmää nimeni(), se menee luokkaan D ja etsii nimeni( ) toiminto. Mutta luokassa D ei ole mitään ilmoitusta. Näin ollen haku siirtyy luokkaan B, saa nimeni() funktio, ja palauttaa tuloksen. Haku tapahtuu seuraavasti.

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

Jos luokalla B ei olisi menetelmää, se kutsuu luokan C menetelmää.

Tässä ehdotamme, että poistat luokan B menetelmän ja tarkistat mitä tapahtuu. Tekemällä tämän saat käsityksen menetelmän resoluution toiminnasta.

Vanha ja uusi tyylijärjestys

Pythonin vanhemmassa versiossa (2.1) saamme käyttää vain vanhoja luokkia, mutta Python (2.2 & jatka), voimme käyttää uusia luokkia. Python 3:ssa on oletusarvoisesti alkuperäiset (uudet) luokat. Uuden tyyliluokan ensimmäinen vanhempi perii Python-juuren 'objekti'-luokasta. Katsotaanpa seuraava esimerkki -

numero aakkoset

Esimerkki -

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

Molempien luokkien ilmoitustyyli on erilainen. Metodin resoluutiossa vanhan tyylin luokat noudattavat syvyys ensin vasemmalta oikealle -algoritmia (DLR), kun taas uudet tyyliluokat käyttävät C3-linearisointialgoritmia suorittaessaan moniperintöä.

DLR-algoritmi

Python luo luettelon luokista toteuttaessaan moniperinnön luokkien välillä. Tätä luetteloa käytetään määrittämään, mikä menetelmä on kutsuttava, jota esiintymät kutsuvat.

Voimme olettaa, että työskentelemme sen nimellä, koska menetelmän resoluutio etsii ensin syvyyttä ja siirtyy sitten vasemmalta oikealle. Alla on esimerkki.

Esimerkki -

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

Ensin algoritmi etsii instanssiluokasta kutsutun menetelmän. Jos ei löydy, se menee esivanhemmille, jos ei myöskään löydy. Se tutkii vanhemman vanhempaa. Tämä jatkuu perimisluokkien loppuun asti.

Yllä olevassa esimerkissä menetelmän resoluutiojärjestys on -

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

Mutta A ei voi olla kahdesti läsnä, joten -

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

Tämä algoritmi näyttää oudon käytöksen tuolloin. Katsotaanpa alla olevaa esimerkkiä.

Esimerkki -

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

DLR-algoritmin mukaan järjestys on E, C, D, B, A. Luokassa C on A & B luokkien vaihto, mikä on hyvin epäselvää. Se tarkoittaa, että algoritmi ei säilytä monotonisuusominaisuutta.

Samuele Perdoni oli ensimmäinen henkilö, joka havaitsi epäjohdonmukaisuuden MRO-algoritmien välillä.

C3 Linearisointialgoritmi

C3-linearisointialgoritmi on parempi versio DLR-algoritmista, koska se poistaa epäjohdonmukaisuuden. Tällä algoritmilla on joitain rajoituksia, jotka on annettu alla.

java poikkeuksia
  • Lasten tulee olla vanhempiaan edeltä.
  • Jos tietty luokka perii yhdestä tai useammasta luokasta, ne tallennetaan perusluokan monikossa määritetyssä järjestyksessä.

C3-linearisointialgoritmin säännöt

  • Menetelmän resoluutiojärjestyksen rakenne määritellään periytymisgraafin avulla.
  • Käyttäjän tulee vierailla superluokassa vasta paikallisten luokkien menetelmien käynnin jälkeen.
  • Säilytä monotonisuus

Method Resolution -luokan menetelmä

Python tarjoaa kaksi tapaa saada luokan menetelmän resoluutiojärjestys - __mro__ attribuutti tai mro() menetelmä. Näiden menetelmien avulla voimme näyttää menetelmän järjestyksen, jossa ne ratkaistaan.

Ymmärretään seuraava esimerkki.

Esimerkki -

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

Lähtö:

 (, , , , ) [, , ] 

Kuten yllä olevassa lähdössä näemme, saamme menetelmän resoluution järjestyksen. Tällä tavalla C3-linearisointialgoritmi toimii useille perinnöille.