Home Insegnanti Contattami Portfolio

Dataclass

dataclasses — Data Classes
Source code: Lib/dataclasses.py This module provides a decorator and functions for automatically adding generated special methods such as__init__() and__repr__() to user-defined classes. It was ori...
https://docs.python.org/3/library/dataclasses.html

0️⃣ Introduzione

Le @dataclass in Python automatizzano la creazione di alcuni metodi speciali per le classi, che altrimenti dovremmo definire manualmente. Questo include metodi come __init__, __repr__, __eq__, semplificando notevolmente la gestione di classi che fungono principalmente da contenitori di dati.


Per utilizzarle, basta importare il decoratore
@dataclass dal modulo dataclasses:

from dataclasses import dataclass

e applicarlo alla classe @dataclass.

1️⃣ Esempio pratico

Vediamo la differenza tra una classe normale e una @dataclass con un esempio concreto.

2️⃣ Dettagli automatici

Quando usiamo @dataclass, Python genera automaticamente i seguenti metodi:

3️⃣ Esempio Avanzato

Ecco un altro esempio, in cui definiamo una classe per un inventario:

from typing import ClassVar

@dataclass
class InventoryItem:
    '''Class for keeping track of an item in inventory'''
    name: str
    unit_price: float
    quantity_on_hand: int = 0
    class_var: ClassVar[int] = 100

In questo modo il costruttore che verrà generato ignorerà la variabile “class_var”.

def __init__(self, name: str, unit_price: float, quantity_on_hand: int = 0):
    self.name = name
    self.unit_price = unit_price
    self.quantity_on_hand = quantity_on_hand

Possiamo vedere come la @dataclass ha semplificato molto la gestione degli attributi della classe.

4️⃣ Come ignorare variabili nella dataclass

In alcuni casi, potremmo voler evitare che alcune variabili vengano considerate nel costruttore generato automaticamente. Per esempio, potremmo avere variabili che non devono essere inizializzate dall'esterno. Possiamo ottenere questo comportamento usando ClassVar.

from typing import ClassVar
from dataclasses import dataclass

@dataclass
class InventoryItem:
    '''Classe per tenere traccia degli articoli di inventario'''
    name: str
    unit_price: float
    quantity_on_hand: int = 0
    class_var: ClassVar[int] = 100

In questo caso, la variabile class_var non sarà inclusa nel costruttore.

5️⃣ Ereditarietà

Classi miste

Quando ereditiamo da una classe che non è una @dataclass, è necessario gestire manualmente alcune parti del processo di inizializzazione. Ad esempio:

from dataclasses import dataclass

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

@dataclass
class Square(Rectangle):
    side: float

    def __post_init__(self):
        super().__init__(self.side, self.side)

È necessario definire il metodo __post_init__ manualmente.

Chiaramente, come precedentemente, per la classe dataclass verranno automaticamente generati i metodi __init__, __repr__ e __eq__

Ereditarietà con sole dataclass

Quando sia la classe base che quella derivata sono @dataclass, Python gestisce tutto automaticamente. Vediamo un esempio:

from dataclasses import dataclass

@dataclass
class Rectangle:
    width: int
    lenght: int

@dataclass
class ColorRectangle(Rectangle):
    color: str
    
rect = ColorRectangle(10, 10, "green")

In questo caso, non è necessario definire manualmente né il costruttore né il metodo __post_init__, poiché tutto viene generato automaticamente da Python.