ProgrammazioneSviluppatore Python Senior

Spiega il modello di eredità e il funzionamento di super() in Python. Quali sono le peculiarità dell'uso di super() nell'ereditarietà multipla e quali errori si possono commettere?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

In Python è supportata l'ereditarietà multipla e le chiamate ai metodi dei genitori sono gestite tramite l'ordine di risoluzione dei metodi lineare (MRO - Method Resolution Order). La funzione super() consente di chiamare un metodo della superclasse nella gerarchia ed è particolarmente utile nell'ereditarietà complessa.

super() garantisce la corretta chiamata dei metodi secondo MRO, e non solo del genitore diretto.

Esempio di codice:

class A: def do(self): print('A') class B(A): def do(self): print('B') super().do() class C(A): def do(self): print('C') super().do() class D(B, C): def do(self): print('D') super().do() D().do() # Stampa: # D # B # C # A

Punti da considerare: Ogni metodo deve chiamare super(), altrimenti MRO "si romperà". Inoltre, i costruttori (__init__) devono chiamare super().__init__().

Domanda insidiosa.

Domanda: Cosa succede se in una gerarchia di ereditarietà multipla una delle classi "dimentica" di chiamare super() nel proprio metodo?

Risposta: MRO sarà violato, alcuni metodi dei genitori non verranno semplicemente chiamati. Esempio:

class A: def show(self): print('A') class B(A): def show(self): print('B') class C(A): def show(self): print('C') super().show() class D(B, C): def show(self): print('D'); super().show() D().show() # Stampa: D B # I metodi C e A non vengono chiamati affatto

Esempi di errori reali dovuti alla mancanza di conoscenza delle sfumature del tema.


Storia

In una grande eredità di componenti GUI, è stato dimenticato di chiamare super().__init__() in una delle classi intermedie. Di conseguenza, uno dei widget non è stato inizializzato correttamente, il che ha causato un "bug" raro.

Storia

In un server REST API, un logger si basava sulla superclasse, che secondo MRO doveva "agganciarsi" a tutte le richieste. Una delle classi ha chiamato il logger direttamente, anziché attraverso super(), il che ha causato una violazione della catena di chiamata e i messaggi non sono stati registrati - il team ha cercato a lungo la causa.

Storia

In una gerarchia complessa di mixin durante gli override, un metodo "dimenticò" di chiamare super(). Questo portò al fatto che da un endpoint API la validazione non funzionava, mentre da un altro - funzionava correttamente. L'errore è stato trovato dopo settimane, studiando manualmente MRO.