lettura facile

Le metaclassi in Python

In Python, una metaclasse è una classe che definisce le classi.

Cosa fa una metaclasse? Una metaclasse controlla la creazione e il comportamento delle classi, proprio come le classi controllano la creazione e il comportamento delle loro istanze. In sostanza, ti permette di modificare il modo in cui le classi vengono costruite e istanziate.

Quando crei una classe in Python, l'interprete crea un oggetto di quella classe, che è di solito un'istanza della metaclasse predefinita `type`.

Ad esempio, crea la classe 'MiaClasse'

class MiaClasse:
     pass

Internamente, Python crea un oggetto tramite la chiamata alla metaclasse 'type'.

MiaClasse = type('MiaClasse', (), {})

La chiamata a `type` crea la nuova classe chiamata 'MiaClasse'.

La nuova classe è senza classi genitore perché la tupla `()` è vuota e senza attributi perché il dizionario `{}` è vuoto.

Quindi, la metaclasse 'type' è la metaclasse predefinita del linguaggio Python.

Questo però non ti impedisce di creare un'altra metaclasse per personalizzare e modificare questo processo di creazione delle classi. Puoi infatti creare delle metaclassi personalizzate che ereditano da `type`.

Definire una metaclasse personalizzata

Per definire una metaclasse personalizzata, devi costruire una classe che eredita direttamente dalla classe 'type'.

Ad esempio, crea una metaclasse chiamata 'MiaMeta'.

class MiaMeta(type):
    def __new__(cls, nome, basi, dct):
        print(f'Stai creando una classe {nome}')
        return super().__new__(cls, nome, basi, dct)

Questa è una metaclasse personalizzata che eredita da `type` e  sovrascrive il metodo `__new__` per aggiungere un comportamento personalizzato durante la creazione della classe.

Il metodo `__new__` viene chiamato prima di `__init__` e si occupa di restituire una nuova istanza della classe.

Per utilizzare la metaclasse 'MiaMeta' quando definisci una nuova classe, devi indicarla tra le parentesi tonde tramite l'attributo metaclass.

Ad esempio, genera una nuova classe chiamata 'MiaClasse'.

class MiaClasse(metaclass=MiaMeta):
    pass

In questo caso la classe 'MiaClasse'  utilizza `MiaMeta` come sua metaclasse.

Questo significa che, al momento della creazione della classe, viene eseguito automaticamente il metodo `__new__` della metaclasse `MiaMeta` che stampa sullo schermo questo messaggio.

Stai creando la classe MiaClasse

In questo esempio banale il metodo `__new__` della metaclasse si limita a stampare un messaggio sullo schermo.

In generale, puoi fargli fare qualsiasi altra cosa. 

Un esempio pratico

Vediamo un esempio pratico di metaclasse personalizzata.

Definisci una metaclasse per assicurati che le nuove classi che la utilizzano abbiano un attributo specifico.

class MiaMeta(type):
    def __new__(cls, nome, basi, dct):
        if 'year' not in dct:
            raise TypeError(f"{nome} non ha l'attributo 'year' ")
        print(f'Stai creando una classe {nome}')
        return super().__new__(cls, nome, basi, dct)

Questa metaclasse controlla se la nuova classe ha definito un attributo chiamato 'year'.

Se non è presente, la metaclasse impedisce la creazione della nuova classe.

Ad esempio, crea una nuova classe che eredita dalla metaclasse 'MiaMeta'.

class MiaClasse1(metaclass=MiaMeta):
    year = 2020

Al momento della creazione Python richiama il metodo '__new__' della metaclasse ed esegue il controllo.

In questo caso la nuova classe ha l'attributo 'year' al suo interno, quindi la nuova classe viene creata.

Stai creando la classe MiaClasse1

Ora prova a creare un'altra classe che eredita dalla classe 'MiaMeta' ma priva dell'attributo richiesto.

class MiaClasse2(metaclass=MiaMeta):
    day = 27

Quando provi a creare la classe senza l'attributo richiesto (year), la metaclasse 'MiaMeta' genera un errore e impedisce la creazione della nuova classe.

TypeError: MiaClasse2 non ha l'attributo 'year'

In questo modo puoi controllare la creazione, l'inizializzazione e la configurazione delle nuovi classi.

Quando utilizzare le metaclassi?

Le metaclassi sono una funzionalità potente e avanzata di Python ma poco conosciute.

Potresti considerare di usarle in situazioni in cui hai bisogno di personalizzare la creazione delle classi.

Ad esempio, puoi usarle per verificare se la nuova classe rispetta alcuni requisiti, contenga attributi o metodi specifici, per applicare automaticamente dei decoratori a tutti i metodi in una classe, ecc..

Ricorda però che le metaclassi possono introdurre un certo livello di complessità nel codice, quindi utilizzale con parsimonia e solo quando è veramente necessario.




Se qualcosa non ti è chiaro, scrivi la tua domanda nei commenti.




FacebookTwitterLinkedinLinkedin