CodeGym /Corsi /Python SELF IT /Ordine di risoluzione dei metodi (MRO)

Ordine di risoluzione dei metodi (MRO)

Python SELF IT
Livello 16 , Lezione 5
Disponibile

11.1 Method Resolution Order

L'ordine di risoluzione dei metodi (Method Resolution Order, MRO) determina la sequenza in cui Python cerca metodi e attributi nell'ereditarietà delle classi. È particolarmente importante quando si lavora con l'ereditarietà multipla, quando una classe può ereditare attributi e metodi da più classi genitrici.

In altre parole, esiste un ordine fisso (o meglio, un algoritmo) secondo cui Python attraversa l'albero delle ereditarietà delle classi. Questo algoritmo assicura un corretto ordine di ricerca dei metodi, che può esser descritto come segue:

Algoritmo di linearizzazione C3

L'algoritmo di linearizzazione C3 determina il MRO combinando:

  • La classe stessa.
  • La lista delle classi genitrici nell'ordine in cui sono elencate.
  • MRO delle classi genitrici nello stesso ordine.

Regole dell'algoritmo di linearizzazione C3

  • Mantenere l'ordine locale dei metodi: se la classe A è indicata prima della classe B, tutti i metodi della classe A devono essere considerati prima dei metodi della classe B.
  • Mantenere l'ordine nei genitori: se la classe A è un genitore della classe B, tutti i metodi della classe A devono essere considerati prima dei metodi della classe B.
  • Considerare l'ordine di ereditarietà: se la classe C è un genitore di due o più classi, l'ordine dei metodi della classe C deve essere mantenuto nel MRO di tutte queste classi.

Passi dell'algoritmo:

Passo 1. Iniziamo con la classe stessa:

Iniziamo sempre con la classe stessa in cui viene chiamato il metodo.

Passo 2. Aggiungiamo le classi base secondo il loro ordine di elencazione:

Dopo la classe corrente, controlliamo le classi base nell'ordine in cui sono elencate durante l'ereditarietà.

Passo 3. Attraversiamo le classi genitrici:

Cerchiamo campi e metodi lì.

Passo 4. Combiniamo MRO delle classi genitrici:

Se la stessa classe base viene ereditata attraverso più percorsi, viene verificata una sola volta e nell'ordine corretto (tutte le altre volte viene saltata).

Per chi è già familiare con il tema "Algoritmi e strutture dati", questo è un percorso in profondità, non in larghezza.

11.2 Verifica del MRO

In Python è possibile verificare l'ordine di ricerca dei metodi e dei campi della classe, usando l'attributo __mro__ o la funzione mro().

Esempio:


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

# Verifica MRO
print(D.__mro__)
        

L'output sarà:


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

Questo mostra l'ordine in cui Python cercherà metodi e attributi:

  • D: Python controlla prima il metodo nella classe D.
  • B: Poi Python controlla il metodo nella classe B (primo genitore).
  • C: Se il metodo non viene trovato nella classe B, Python controlla il metodo nella classe C (secondo genitore).
  • A: Se il metodo non viene trovato nelle classi B e C, Python controlla il metodo nella classe A.
  • object: Infine, Python controlla il metodo nella classe base object.

11.3 Uso di super() con MRO

La funzione super() segue il MRO per chiamare i metodi delle classi genitrici nel giusto ordine. Consideriamo un esempio di utilizzo di 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()
        

L'output sarà il seguente:


D
B
C
A
        

Ordine di ricerca (MRO)

1. Chiamata del metodo method della classe D:

  • Python controlla prima il metodo nella classe D e lo trova lì.
  • Il metodo D.method() viene eseguito e stampa "D".
  • Poi viene chiamato super().method(), che segue MRO per chiamare il metodo successivo.

2. Chiamata del metodo method della classe B:

  • Secondo MRO, la classe successiva dopo D è B.
  • Il metodo B.method() viene eseguito e stampa "B".
  • Poi viene chiamato super().method(), che segue MRO per chiamare il metodo successivo.

3. Chiamata del metodo method della classe C:

  • La classe successiva nel MRO dopo B è C.
  • Il metodo C.method() viene eseguito e stampa "C".
  • Poi viene chiamato super().method(), che segue MRO per chiamare il metodo successivo.

4. Chiamata del metodo method della classe A:

  • La classe successiva nel MRO dopo C è A.
  • Il metodo A.method() viene eseguito e stampa "A".
  • Poi viene chiamato super().method(), ma poiché A non ha metodi genitrici method (a parte object), la chiamata finisce senza ulteriori azioni.
1
Опрос
Ereditarietà,  16 уровень,  5 лекция
недоступен
Ereditarietà
Ereditarietà
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION