CodeGym /Kursy /Python SELF PL /Porządek rozwiązywania metod (MRO)

Porządek rozwiązywania metod (MRO)

Python SELF PL
Poziom 16 , Lekcja 5
Dostępny

11.1 Method Resolution Order

Porządek rozwiązywania metod (Method Resolution Order, MRO) określa kolejność, w jakiej Python szuka metod i atrybutów w hierarchii klas. Jest to szczególnie ważne przy pracy z wielodziedziczeniem, gdy klasa może dziedziczyć atrybuty i metody z kilku klas macierzystych.

Mówiąc ogólnie, istnieje ścisły, określony porządek (albo raczej algorytm), według którego Python przeszukuje drzewo dziedziczenia klas. Ten algorytm zapewnia poprawny porządek wyszukiwania metod, który można opisać następująco:

Algorytm C3-linearizacji

Algorytm C3-linearizacji określa MRO przez łączenie:

  • Samo klasy.
  • Listy klas macierzystych w kolejności ich wymienienia.
  • MRO klas macierzystych w tej samej kolejności.

Zasady algorytmu C3-linearizacji

  • Zachowanie lokalnego porządku metod: jeśli klasa A jest wymieniona przed klasą B, wszystkie metody klasy A powinny być rozważane przed metodami klasy B.
  • Utrzymanie porządku w klasach rodzicielskich: jeśli klasa A jest rodzicem klasy B, wszystkie metody klasy A powinny być rozważane przed metodami klasy B.
  • Uważanie na porządek dziedziczenia: jeśli klasa C jest rodzicem dla dwóch lub więcej klas, porządek metod klasy C powinien być zachowany w MRO wszystkich tych klas.

Kroki algorytmu:

Krok 1. Zaczynamy od samej klasy:

Zawsze zaczynamy od klasy, w której metoda została wywołana.

Krok 2. Dodajemy klasy bazowe w kolejności ich wymienienia:

Po bieżącej klasie sprawdzamy klasy bazowe w takiej kolejności, w jakiej zostały wymienione przy dziedziczeniu.

Krok 3. Przechodzimy przez klasy rodzicielskie:

Szukamy tam pól i metod.

Krok 4. Łączymy MRO klas rodzicielskich:

Jeśli ta sama klasa bazowa jest dziedziczona przez kilka ścieżek, jest sprawdzana tylko jeden raz i w poprawnej kolejności (wszystkie inne razy zostaje pominięta).

Dla tych, którzy już są zaznajomieni z tematem „Algorytmy i struktury danych”, jest to przeszukiwanie w głąb, a nie wszerz.

11.2 Sprawdzanie MRO

W Pythonie można sprawdzić kolejność przeszukiwania metod i pól klasy, używając atrybutu __mro__ lub funkcji mro().

Przykład:


class A:
    def method(self):
        print("A")
        
class B(A):
    def method(self):
        print("B")
        
class C(A):
    def method(self):
        print("C")
        
class D(B, C):
    def method(self):
        print("D")
        

# Sprawdzanie MRO
print(D.__mro__)
        

Wynik będzie:


(<class '__main__.D'>, 
<class '__main__.B'>, 
<class '__main__.C'>,
<class '__main__.A'>,
<class 'object'>)
        

To pokazuje kolejność, w jakiej Python będzie szukać metod i atrybutów:

  • D: Python najpierw sprawdza metodę w klasie D.
  • B: Następnie Python sprawdza metodę w klasie B (pierwsza klasa rodzicielska).
  • C: Jeśli metoda nie jest znaleziona w klasie B, Python sprawdza metodę w klasie C (druga klasa rodzicielska).
  • A: Jeśli metoda nie jest znaleziona w klasach B i C, Python sprawdza metodę w klasie A.
  • object: Na koniec, Python sprawdza metodę w bazowej klasie object.

11.3 Użycie super() z MRO

Funkcja super() podąża za MRO, aby wywołać metody klas rodzicielskich w poprawnej kolejności. Zobaczmy przykład użycia super():

class A:
    def method(self):
        print("A")
        super().method()
        
class B(A):
    def method(self):
        print("B")
        super().method()
        
class C(A):
    def method(self):
        print("C")
        super().method()
        
class D(B, C):
    def method(self):
        print("D")
        super().method()
        
        
d = D()
d.method()
        

Wynik będzie następujący:


D
B
C
A
        

Kolejność przeszukiwania (MRO)

1. Wywołanie metody method klasy D:

  • Python najpierw sprawdza metodę w klasie D i znajduje ją tam.
  • Metoda D.method() jest wykonywana i drukuje "D".
  • Następnie wywoływane jest super().method(), które podąża za MRO, aby wywołać następną metodę.

2. Wywołanie metody method klasy B:

  • Zgodnie z MRO, następną klasą po D jest B.
  • Metoda B.method() jest wykonywana i drukuje "B".
  • Następnie wywoływane jest super().method(), które podąża za MRO, aby wywołać następną metodę.

3. Wywołanie metody method klasy C:

  • Następną klasą w MRO po B jest C.
  • Metoda C.method() jest wykonywana i drukuje "C".
  • Następnie wywoływane jest super().method(), które podąża za MRO, aby wywołać następną metodę.

4. Wywołanie metody method klasy A:

  • Następną klasą w MRO po C jest A.
  • Metoda A.method() jest wykonywana i drukuje "A".
  • Następnie wywoływane jest super().method(), ale ponieważ A nie ma rodzicielskich metod method (oprócz object), wywołanie zakończy się bez dalszych działań.
1
Опрос
Dziedziczenie,  16 уровень,  5 лекция
недоступен
Dziedziczenie
Dziedziczenie
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION