logo

Vrstni red razrešitve metode v Pythonu

V tej vadnici bomo spoznali vrstni red razreševanja metode, ki je znan tudi kot MRO. Je bistveni koncept dedovanja Python.

Vrstni red razrešitve metode opisuje iskalno pot razreda, ki Python uporablja za pridobitev ustrezne metode v razredih, ki vsebujejo večkratno dedovanje.

Uvod

Kot vemo, se razred, ki se deduje, imenuje podrazred ali nadrejeni razred, medtem ko je razred, ki deduje, znan kot podrejeni razred ali podrazred. Pri večkratnem dedovanju je lahko razred sestavljen iz številnih funkcij, zato se tehnika vrstnega reda razrešitve metode uporablja za iskanje vrstnega reda, v katerem se izvaja osnovni razred.

Preprosto povedano – 'Metoda ali atributi so raziskani v trenutnem razredu, če metoda ni prisotna v trenutnem razredu, se iskanje premakne v nadrejene razrede in tako naprej'. To je primer iskanja v globino.

Ima bistveno vlogo pri večkratnem dedovanju, kjer je isto metodo mogoče najti v več nadrazredih.

Da bi ga bolje razumeli, poglejmo, kako ga lahko uporabimo.

terminal kali linux

Primer -

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

Izhod:

 I am a class C 

Pojasnilo -

V zgornji kodi obstaja večkratno dedovanje. Definirali smo tri razrede, imenovane A, B in C, in ti razredi imajo imenovano metodo z istim imenom moje ime(). Ustvarili smo objektni razred C. Objekt je poklical razred C, ne razreda, medtem ko je razred C podedoval metodo razreda A.

Vrstni red je v zgornji kodi razred B -> razred A. Ta tehnika je znana kot MRO (method resolution order).

Razumejmo še en primer večkratnega dedovanja.

Primer -

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

Izhod:

 I am a class B 

Pojasnilo -

V zgornji kodi smo ustvarili še en razred D brez definiranja atributov razreda, ki je podedoval razreda B in C. Ko smo priklicali metodo moje ime(), gre v razred D in išče moje ime( ) funkcijo. Toda razred D nima nobene deklaracije. Zato se iskanje prenese v razred B, dobi moje ime() funkcijo in vrne rezultat. Iskanje bo potekalo na naslednji način.

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

Če razred B ne bi imel metode, bo priklical metodo razreda C.

Tukaj predlagamo, da odstranite metodo razreda B in preverite, kaj se zgodi. S tem boste dobili predstavo o tem, kako deluje ločljivost metode.

poskusi catch catch java

Stari in novi stilski red

V starejši različici Pythona (2.1) smo omejeni na uporabo starih razredov, vendar Python (2.2 in nadaljuj), lahko uporabimo nove razrede. Privzeto ima Python 3 izvirne (nove) razrede. Prvi nadrejeni razred novega sloga podeduje Pythonov korenski razred 'objekt'. Poglejmo naslednji primer -

sklad v javi

Primer -

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

Slog deklaracije obeh razredov je drugačen. Pri razrešitvi metode razredi starega sloga sledijo algoritmu najprej v globino od leve proti desni (DLR), medtem ko novi razredi sloga uporabljajo algoritem linearizacije C3, medtem ko izvajajo večkratno dedovanje.

Algoritem DLR

Python ustvari seznam razredov, medtem ko izvaja večkratno dedovanje med razredi. Ta seznam se uporablja za določanje, katero metodo je treba klicati in jo kličejo primerki.

Predvidevamo lahko, da delamo po njegovem imenu, saj bo ločljivost metode najprej iskala globino, nato pa šla od leve proti desni. Spodaj je primer.

Primer -

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

Najprej bo algoritem v razredu instance poiskal priklicano metodo. Če se ne najde, gre v prve starše, če se tudi ne najde. Pogledal bo nadrejenega nadrejenega. To se bo nadaljevalo do konca dednih razredov.

V zgornjem primeru bo vrstni red razrešitve metode -

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

Toda A ne more biti dvakrat prisoten, tako da -

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

Ta algoritem prikazuje nenavadno obnašanje v tistem času. Oglejmo si spodnji primer.

Primer -

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

V skladu z algoritmom DLR bo vrstni red E, C, D, B, A. Obstaja izmenjava razredov A in B v razredu C, kar je zelo dvoumno. To pomeni, da algoritem ne ohranja lastnosti monotonosti.

Samuele Perdoni je bil prvi, ki je odkril nedoslednost med algoritmi MRO.

C3 linearizacijski algoritem

Algoritem linearizacije C3 je boljša različica algoritma DLR, ker odpravlja nedoslednost. Ta algoritem ima nekaj omejitev, ki so navedene spodaj.

  • Otroci morajo biti pred starši.
  • Če določen razred podeduje enega ali več razredov, se ti shranijo v vrstnem redu, določenem v tuple osnovnega razreda.

Pravila linearizacijskega algoritma C3

  • Struktura vrstnega reda razrešitve metode določa graf dedovanja.
  • Uporabnik mora obiskati super razred šele potem, ko obišče metode lokalnih razredov.
  • Ohranite monotonost

Metoda za razred ločljivosti metode

Python ponuja dva načina za pridobitev vrstnega reda ločljivosti metode razreda - __mro__ atribut oz mro() metoda. S pomočjo teh metod lahko prikažemo vrstni red metod, v katerem so razrešene.

Razumejmo naslednji primer.

Primer -

primerjaj niz java
 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()) 

Izhod:

 (, , , , ) [, , ] 

Kot lahko vidimo v zgornjem izhodu, dobimo vrstni red ločljivosti metode. Na tak način linearizacijski algoritem C3 deluje za večkratno dedovanje.