Cosa sono i metodi magici in Python e come usarli

Una delle caratteristiche meno conosciute ma preziose di Python è la capacità di implementare metodi magici sugli oggetti. Usando metodi magici, possiamo scrivere codice più pulito, intuitivo e facile da capire.

Con i metodi magici, possiamo creare interfacce per interagire con gli oggetti in un modo che sembri più Pythonic. Questo articolo ti introdurrà ai metodi magici, discuterà le migliori pratiche per crearli ed esplorerà i metodi magici comuni che incontrerai.

Cosa sono i metodi magici?

I metodi magici sono metodi Python che definiscono come si comportano gli oggetti Python quando vengono eseguite operazioni comuni su di essi. Questi metodi sono definiti distintamente con doppi caratteri di sottolineatura prima e dopo il nome del metodo.

Di conseguenza, sono comunemente chiamati metodi dunder, come in doppia sottolineatura. Un metodo dunder comune che potresti aver già incontrato è il metodo __init__() utilizzato per definire i costruttori di classi.

In genere, i metodi dunder non sono pensati per essere chiamati direttamente nel codice; piuttosto, saranno chiamati dall’interprete mentre il programma è in esecuzione.

Perché i metodi magici sono utili?

I metodi magici sono un concetto utile nella programmazione orientata agli oggetti in Python. Usandoli, specifichi il comportamento dei tuoi tipi di dati personalizzati quando vengono utilizzati con operazioni integrate comuni. Queste operazioni includono:

🟢 Operazioni aritmetiche

🟢 Operazioni di confronto

🟢 Operazioni del ciclo di vita

🟢 Operazioni di rappresentanza

La sezione seguente discuterà come implementare i metodi magici che definiscono come si comporta l’applicazione quando viene utilizzata in tutte le categorie di cui sopra.

Come definire i metodi magici

Come accennato in precedenza, i metodi magici specificano il comportamento degli oggetti. In quanto tali, sono definiti come parte della classe dell’oggetto. Poiché fanno parte della classe dell’oggetto, accettano come primo argomento self che è un riferimento all’oggetto stesso.

Possono accettare argomenti aggiuntivi a seconda di come verranno chiamati dall’interprete. Sono anche definiti distintamente con due trattini bassi prima e dopo i loro nomi.

Implementazione

Gran parte di ciò che abbiamo discusso finora sembra teorico e astratto. In questa sezione implementeremo una semplice classe Rectangle.

Questa classe avrà proprietà di lunghezza e larghezza. Utilizzando il metodo __init__, è possibile specificare queste proprietà durante l’istanza. Inoltre, potrai confrontare diversi rettangoli per vedere se è uguale, minore o maggiore di un altro utilizzando gli operatori ==, < e >. Infine, il rettangolo dovrebbe essere in grado di fornire una rappresentazione di stringa significativa.

Impostazione dell’ambiente di codifica

Per seguire questa procedura dettagliata, avrai bisogno di un ambiente di runtime Python. Puoi usarne uno locale o puoi usare il compilatore online winadmin.it Python.

Creazione della classe Rectangle

Innanzitutto, iniziamo definendo la classe Rectangle.

class Rectangle:
    pass

Creazione del metodo costruttore

Successivamente, creiamo il nostro primo metodo magico, il metodo del costruttore di classi. Questo metodo prenderà l’altezza e la larghezza e le memorizzerà come attributi nell’istanza della classe.

class Rectangle:
    def __init__(self, height, width):
        self.height = height
        self.width = width

Creazione di un metodo magico per la rappresentazione delle stringhe

Successivamente, vogliamo creare un metodo che consenta alla nostra classe di generare una stringa leggibile dall’uomo per rappresentare l’oggetto. Questo metodo verrà chiamato ogni volta che chiamiamo la funzione str() passando un’istanza della classe Rectangle come argomento. Questo metodo verrà chiamato anche quando si chiamano funzioni che prevedono un argomento stringa, come la funzione print.

class Rectangle:
    def __init__(self, height, width):
        self.height = height
        self.width = width

    def __str__(self):
        return f'Rectangle({self.height}, {self.width})'

Il metodo __str__() dovrebbe restituire una stringa che vorresti rappresentare l’oggetto. In questo caso, viene restituita una stringa del formato Rectangle(, ) dove altezza e larghezza sono le dimensioni memorizzate del rettangolo.

Creazione di metodi magici per operazioni di confronto

Successivamente, vogliamo creare operatori di confronto per le operazioni uguale a, minore di e maggiore di. Questo è chiamato sovraccarico dell’operatore. Per crearli, usiamo rispettivamente i metodi magici __eq__, __lt__ e __gt__. Questi metodi restituiranno un valore booleano dopo aver confrontato le aree dei rettangoli.

class Rectangle:
    def __init__(self, height, width):
        self.height = height
        self.width = width

    def __str__(self):
        return f'Rectangle({self.height}, {self.width})'

    def __eq__(self, other):
        """ Checking for equality """
        return self.height * self.width == other.height * other.width

    def __lt__(self, other):
        """ Checking if the rectangle is less than the other one """
        return self.height * self.width < other.height * other.width

    def __gt__(self, other):
        """ Checking if the rectage is greater than the other one """
        return self.height * self.width > other.height * other.width

Come puoi vedere, questi metodi accettano due parametri. Il primo è il rettangolo corrente e il secondo è l’altro valore con cui viene confrontato. Questo valore può essere un’altra istanza Rectangle o qualsiasi altro valore. La logica di come il confronto e le condizioni in cui il confronto restituirà true dipendono completamente da te.

Metodi magici comuni

In questa prossima sezione, discuteremo i metodi magici comuni che incontrerai e utilizzerai.

#1. Operazioni aritmetiche

I metodi magici aritmetici vengono chiamati quando un’istanza della tua classe viene posizionata sul lato sinistro di un segno aritmetico. Il metodo verrà chiamato con due argomenti, il primo è un riferimento all’istanza. Il secondo valore è l’oggetto a destra del segno. Le modalità e le indicazioni sono le seguenti:

NomeMetodoSegnoDescrizioneAggiunta__aggiungi__+Implementa l’addizione. Subtraction__sub__–Implementa la sottrazione.Moltiplicazione__mul__*Implementa la moltiplicazioneDivision__div__/Implementa la divisione.Floor division__floordiv__//Implementa la divisione floor.

#2. Operazioni di confronto

Come i metodi magici aritmetici, questi metodi vengono chiamati quando un’istanza della classe per cui sono definiti viene posizionata a sinistra dell’operatore di confronto. Inoltre, come i metodi magici aritmetici, sono chiamati con due parametri; il primo è un riferimento all’istanza dell’oggetto. Il secondo è un riferimento al valore sul lato destro del segno.

NomeMetodoSegnoDescrizioneMinore di__lt__Implementa il confronto maggiore diEqual to__eq__==Implementa il confronto uguale aMinore o uguale a__le__>=Implementa il confronto minore o uguale aGrande o uguale a__ge__<=Implementa il confronto maggiore o uguale a confronto

#3. Operazioni del ciclo di vita

Questi metodi verranno chiamati in risposta ai diversi metodi del ciclo di vita di un oggetto, come l’istanziazione o l’eliminazione. Il costruttore, __init__ rientra in questa categoria. I metodi comuni in questa categoria sono elencati nella tabella seguente:

NameMethodDescriptionConstructor__init__Questo metodo viene chiamato ogni volta che un oggetto della classe per cui è definito viene eliminato. Può essere utilizzato per eseguire azioni di pulizia come la chiusura di tutti i file che aveva aperto.Deletion__del__Questo metodo viene chiamato ogni volta che un oggetto della classe per cui è definito viene eliminato. Può essere utilizzato per eseguire azioni di pulizia come la chiusura di tutti i file che aveva aperto. New__new__Il metodo __new__ viene chiamato per primo quando viene istanziato un oggetto della classe specificata. Questo metodo viene chiamato prima del costruttore e accetta la classe nonché eventuali argomenti aggiuntivi. Restituisce un’istanza della classe. Per la maggior parte, non è troppo utile, ma è trattato in dettaglio qui.

#4. Operazioni di rappresentanza

NameMethodDescriptionStr__str__Restituisce una rappresentazione in forma di stringa leggibile dall’utente dell’oggetto. Questo metodo viene chiamato quando chiamate la funzione str(), passando un’istanza della classe come argomento. Viene chiamato anche quando si passa l’istanza alle funzioni print() e format(). Ha lo scopo di fornire una stringa comprensibile per l’utente finale dell’applicazione.Repr__repr__Restituisce una rappresentazione in forma di stringa dell’oggetto utilizzato dallo sviluppatore. Idealmente, la stringa restituita dovrebbe essere ricca di informazioni in modo tale da poter costruire un’istanza identica dell’oggetto solo dalla stringa.

Migliori pratiche per la creazione di metodi magici

I metodi magici sono incredibili e semplificheranno il tuo codice. Tuttavia, è importante tenere a mente le seguenti cose quando li usi.

  • Usali con parsimonia: l’implementazione di troppi metodi magici nelle tue classi rende il tuo codice difficile da capire. Limitati ad implementare solo quelli essenziali.
  • Assicurati di comprendere le implicazioni sulle prestazioni di metodi come __setatrr__ e __getattr__ prima di utilizzarli.
  • Documenta il comportamento dei tuoi metodi magici in modo che altri sviluppatori possano sapere esattamente cosa fanno. Questo rende più facile per loro usarli ed eseguire il debug quando necessario.

Parole finali

In questo articolo, ho introdotto i metodi magici come un modo per creare classi che possono essere utilizzate con operazioni integrate. Ho anche discusso di come sono definiti e ho esaminato un esempio di una classe implementata dai metodi magici. Successivamente, ho menzionato i diversi metodi che probabilmente utilizzerai e di cui avrai bisogno prima di condividere alcune best practice da tenere a mente.

Successivamente, potresti voler imparare come implementare la classe Counter in Python.