V tomto tutoriálu se seznámíme s pořadím rozlišení metod, které je také známé jako MRO. Je to základní koncept dědičnosti Pythonu.
Pořadí rozlišení metody popisuje cestu hledání třídy, která Krajta používá k získání příslušné metody ve třídách, které obsahují vícenásobnou dědičnost.
Úvod
Jak víme, třída, která je zděděna, se nazývá třída Subclass nebo Parent, zatímco třída, která dědí, je známá jako podtřída nebo podtřída. Ve vícenásobné dědičnosti se třída může skládat z mnoha funkcí, takže technika pořadí rozlišení metod se používá k prohledávání pořadí, ve kterém se provádí základní třída.
Jednoduše řečeno - 'Metoda nebo atributy jsou prozkoumány v aktuální třídě, pokud metoda není přítomna v aktuální třídě, hledání se přesune do nadřazených tříd atd.'. Toto je příklad hloubkového hledání.
Hraje zásadní roli ve vícenásobné dědičnosti, kde lze stejnou metodu nalézt ve více nadtřídách.
Abychom tomu porozuměli lépe, podívejme se, jak to můžeme použít.
Příklad -
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())
Výstup:
I am a class C
Vysvětlení -
Ve výše uvedeném kódu je vícenásobná dědičnost. Definovali jsme tři třídy nazvané A, B a C a tyto třídy mají metodu stejného názvu moje jméno(). Vytvořili jsme třídu objektu C. Objekt vyvolal třídu C, nikoli třídu, zatímco třída C zdědila metodu třídy A.
Pořadí je dodrženo ve výše uvedeném kódu je třída B -> třída A. Tato technika je známá jako MRO (method resolution order).
java int zdvojnásobit
Pojďme pochopit další příklad vícenásobné dědičnosti.
Příklad -
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()
Výstup:
I am a class B
Vysvětlení -
Ve výše uvedeném kódu jsme vytvořili další třídu D bez definování atributů třídy, která zdědila třídu B a C. Když jsme vyvolali metodu moje jméno(), přejde do třídy D a hledá moje jméno( ) funkce. Ale třída D žádnou deklaraci nemá. Hledání se tedy přenese do třídy B, dostane moje jméno() funkci a vrátí výsledek. Vyhledávání bude probíhat následovně.
Class D -> Class B -> Class C -> Class A
Pokud by třída B neměla metodu, vyvolá metodu třídy C.
Zde navrhujeme odstranit metodu třídy B a zkontrolovat, co se stane. Tímto způsobem získáte představu o tom, jak funguje rozlišení metody.
Řád starého a nového stylu
Ve starší verzi Pythonu (2.1) jsme omezeni na používání starých tříd, ale Krajta (2.2 a pokračovat), můžeme použít nové třídy. Ve výchozím nastavení má Python 3 původní (nové) třídy. První rodič nové třídy stylu dědí z kořenové třídy 'objektu' Pythonu. Podívejme se na následující příklad -
Příklad -
# Old style class class OldStyleClass: pass # New style class class NewStyleClass(object): pass
Styl deklarace obou tříd je odlišný. V rozlišení metod třídy starého stylu následují algoritmus hloubka první zleva doprava (DLR), zatímco nové třídy stylu používají algoritmus C3 linearizace při provádění vícenásobné dědičnosti.
Algoritmus DLR
Python vytváří seznam tříd při implementaci vícenásobné dědičnosti mezi třídami. Tento seznam se používá k určení, která metoda musí být volána, kterou instance vyvolá.
Můžeme předpokládat, že pracuje podle názvu, protože rozlišení metody nejprve prohledá hloubku a poté půjde zleva doprava. Níže je uveden příklad.
nfa na dfa
Příklad -
class A: pass class B: pass class C(A, B): pass class D(B, A): pass class E(C,D): pass
Nejprve algoritmus vyhledá v instanční třídě vyvolanou metodu. Pokud není nalezen, přejde do prvního rodiče, pokud není nalezen také. Podívá se na rodiče rodiče. Toto bude pokračovat až do konce dědických tříd.
Ve výše uvedeném příkladu bude pořadí rozlišení metody -
class D -> class B -> class A -> class C -> class A
Ale A nemůže být dvakrát přítomno, takže -
class D -> class B -> class A -> class C ->
Tento algoritmus ukazuje podivné chování v té době. Podívejme se na níže uvedený příklad.
Příklad -
class A: pass class B: pass class C(A, B): pass class D(B, A): pass class E(C,D): pass
Podle DLR Algorithm bude pořadí E, C, D, B, A. Ve třídě C dochází k záměně tříd A a B, což je velmi nejednoznačné. To znamená, že algoritmus nezachovává vlastnost monotónnosti.
Samuele Perdoni byl první člověk, který objevil nekonzistenci mezi algoritmy MRO.
Linearizační algoritmus C3
Linearizační algoritmus C3 je lepší verzí algoritmu DLR, protože odstraňuje nekonzistenci. Tento algoritmus má některá omezení, která jsou uvedena níže.
- Děti musí předcházet své rodiče.
- Pokud určitá třída dědí z jedné nebo více tříd, uloží se v pořadí zadaném v n-tici základní třídy.
Pravidla linearizačního algoritmu C3
- Struktura pořadí rozlišení metody je definována grafem dědičnosti.
- Uživatel musí navštívit super třídu až poté, co navštíví metody místních tříd.
- Zachovat monotónnost
Metoda pro třídu Method Resolution
Python poskytuje dva způsoby, jak získat pořadí rozlišení metod třídy - __mro__ atribut nebo mro() metoda. Pomocí těchto metod můžeme zobrazit pořadí metod, ve kterých jsou řešeny.
Pojďme pochopit následující příklad.
Příklad -
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())
Výstup:
(, , , , ) [, , ]
Jak můžeme vidět na výše uvedeném výstupu, dostáváme pořadí pořadí rozlišení metody. Tímto způsobem pracuje linearizační algoritmus C3 pro vícenásobnou dědičnost.