Crea facilmente classi in Python con @dataclass
In Python, il @dataclassdecoratore semplifica il processo di creazione delle classi aggiungendo automaticamente metodi comuni e promuovendo le migliori pratiche per scrivere codice ben scritto e sicuro. È disponibile da Python 3.7. In questo articolo vi parlerò di questo decoratore.
Iniziamo con un semplice esempio:
Definendo due variabili statiche con suggerimenti di tipo e aggiungendo il @dataclassdecoratore, otteniamo una classe con un __init__metodo corrispondente al seguente:
Sebbene saltare il __init__metodo sia utile, la dataclass offre molto di più di questo. Per capire cosa, diamo un'occhiata alle opzioni disponibili per il decoratore:
Ho omesso alcuni degli argomenti e mantenuto quelli che ritengo più importanti da discutere. Si noti che utilizzando:
comporterà in modo equivalente l'utilizzo degli argomenti predefiniti.
Come si può vedere, a seconda degli argomenti, i metodi verranno aggiunti implicitamente alla classe. Per impostazione predefinita:
- init=True aggiungerà
__init__come abbiamo visto sopra - repr=True aggiungerà
__repr__, cioè ciò che viene mostrato durante la stampa - eq=True aggiungerà
__eq__in base ai campi - order=True aggiungerà
__lt__(),__le__(),__gt__()e__ge__()
Nota che ovviamente puoi anche definire altri metodi di classe personalizzati come faresti normalmente in una classe. Di seguito definisco una classe semplice senza il decoratore @dataclass per il confronto.
Stampa
Con repr=True, che è l'impostazione predefinita, l'output durante la stampa viene modificato. Confrontiamo cosa __repr__mostrano l'oggetto creato con la classe dati e l'oggetto creato con la classe normale (senza ) quando vengono stampati:
Come si può vedere con la classe normale, le informazioni stampate ci dicono molto poco sull'oggetto per impostazione predefinita. D'altra parte, la dataclass mostra sinteticamente i valori dell'oggetto, avendo sovrascritto il default __repr__-method.
Uguaglianza
Il comportamento predefinito dell'uguaglianza per le classi personalizzate può creare confusione. Se confronti una classe personalizzata senza un __eq__metodo definito, due oggetti saranno uguali solo se sono esattamente lo stesso oggetto:
Pertanto, i valori degli attributi non contano. Ma utilizzando la dataclass e eq=True(impostata per impostazione predefinita) viene aggiunta la forma di uguaglianza più prevista in cui gli attributi vengono confrontati (ovvero __eq__viene sovrascritto):
Ordine
Impostando il orderparametro su true (false per impostazione predefinita) e eq su true ( other=Truee eq=Falsecauserà la generazione di un errore) i metodi:
__lt__()__le__()__gt__()__ge__()
Immutabilità e hashing
Infine, parliamo degli argomenti frozene unsafe_hash. Questi argomenti sono molto utili e facilitano la corretta gestione di hashing, uguaglianza e mutazione. Se non hai familiarità con l'hashing in Python, ti consiglio di leggere l'articolo: Understanding Hashing and Equality in Python with __hash__ and __eq__ .
L'impostazione frozen=Trueafferma che la classe deve essere di sola lettura o immutabile, ovvero dopo l'inizializzazione di un oggetto, nessun campo può essere modificato:
Le due proprietà frozene eqinfluenzeranno il metodo di hashing implicito che viene creato:
frozen=True, eq=True=> un__hash__metodo viene generato automaticamente utilizzando i campifrozen=True, eq=False=> default__hash__-method, cioè non usare i campifrozen=False, eq=True=> Unhashable, viene generato un errore in caso di hashfrozen=False, eq=False=> default__hash__-method, cioè non usare i campi
Ma perché la classe deve essere congelata? Se aggiungi un oggetto a un set o a un dizionario, l'hash generato viene utilizzato per posizionarlo all'interno della mappa hash. Successivamente, quando vuoi recuperare l'oggetto, usi lo stesso hash per trovarlo. Ora, se l'oggetto è stato modificato, dovrebbe cambiare anche l'hash (poiché è basato sui campi). Di conseguenza, non sarai più in grado di ritrovare l'oggetto. Pertanto, affinché l'hash rimanga costante, i campi su cui si basa devono rimanere costanti. Per questo motivo, if eq=Truee frozen=False, non è disponibile alcun metodo hash.
Che dire unsafe_hash? Come descritto, il comportamento predefinito della definizione implicita di __hash__si basa su principi che promuovono le migliori pratiche. Tuttavia, se desideri comunque avere un __hash__metodo definito comunque, forse a causa di circostanze speciali, puoi impostarlo unsafe_hash=Truee lo farà. Ma tieni presente che la parola chiave unsafe è lì per un motivo:
Conclusione
@dataclass in Python è un utile decoratore che ci consente di risparmiare tempo, seguire le migliori pratiche e semplificare il processo di creazione delle classi. Credo che sia adatto a un'ampia varietà di situazioni.
Grazie per aver letto!
Potrebbero interessarti anche:

![Che cos'è un elenco collegato, comunque? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































