Salt la conținutul principal
Modulul 9 · Lecția 2 din 434/36 în curs~12 min
Lecții din modul (2/4)

dataclass: clase de date fără boilerplate

Decoratorul @dataclass (modulul dataclasses) generează automat __init__, __repr__ și __eq__ pentru clasele a căror singură sarcină este să ține date. Mai puțin boilerplate, cod mai clar.

Fără clasă de date (boilerplate)

Python
class Punto:
    def __init__(self, x: float, y: float) -> None:
        self.x = x
        self.y = y
    def __repr__(self) -> str:
        return f"Punto(x={self.x}, y={self.y})"
    def __eq__(self, other) -> bool:
        if not isinstance(other, Punto):
            return NotImplemented
        return (self.x, self.y) == (other.x, other.y)

Cu dataclass

Python
from dataclasses import dataclass

@dataclass
class Punto:
    x: float
    y: float

p = Punto(3, 4)
p             # Punto(x=3, y=4)   ← __repr__ gratis
Punto(3, 4) == Punto(3, 4)        # True ← __eq__ gratis
p.x, p.y      # 3, 4

Model: declarați câmpurile ca adnotări de clasă (name: type), opțional cu o valoare implicită. @dataclass generează restul.

Default și default_factory

Python
from dataclasses import dataclass, field

@dataclass
class Articolo:
    nome: str
    prezzo: float = 0.0
    tag: list[str] = field(default_factory=list)

frozen=Adevărat: imuabil

Python
@dataclass(frozen=True)
class Coordinata:
    lat: float
    lon: float

c = Coordinata(45.4, 9.2)
c.lat = 99   # FrozenInstanceError!

Clasele de date frozen sunt, de asemenea, hashable: le puteți folosi ca taste dict sau elemente de set.

ordine=Adevărat: comparații automate

Python
@dataclass(order=True)
class Voto:
    valore: int

Voto(10) < Voto(20)   # True
sorted([Voto(30), Voto(10), Voto(20)])

Generează __lt__, __le__, __gt__, __ge__ comparând câmpuri în ordine au fost declarate.

Metode normale

Clasele de date rămân clase obișnuite: puteți adăuga metode.

Python
import math
from dataclasses import dataclass

@dataclass
class Punto:
    x: float
    y: float
    def distanza_dall_origine(self) -> float:
        return math.hypot(self.x, self.y)

Punto(3, 4).distanza_dall_origine()   # 5.0

Clase de date imuabile și eficiente

Puteți face o clasă de date imuabilă pasând argumentul frozen=True decoratorului: @dataclass(frozen=True). Acest lucru generează o eroare la orice încercare de mutare a atributelor după instanțiere, făcând instanțele sigure pentru medii concurente sau pentru utilizare ca chei de dicționar.

Încercați-l singur

Exercițiu#python.m9.l2.e1
Încercări: 0Se încarcă…

Creați o clasă de date `Book` cu câmpurile `title: str` și `pages: int`. Instanțiați-l ca `l = Book('Moby Dick', 635)`. Evaluați `l == Book('Moby Dick', 635)`.

Se încarcă editorul...
Afișează indiciu

@dataclass generează __eq__ comparând câmp cu câmp.

Soluție disponibilă după 3 încercări

Exercițiu de revizuire

Exercițiu#python.m9.l2.e2
Încercări: 0Se încarcă…

Creați o clasă de date `Coș` cu câmpul `items: list[str]` cu default_factory=list. Instanciați `c1 = Basket()` și `c2 = Basket()`, adăugați 'mela' la c1.items. Evaluați `(c1.items, c2.items)` pentru a verifica că NU sunt aceeași listă.

Se încarcă editorul...
Afișează indiciu

field(default_factory=list) garantează o nouă listă per instanță.

Soluție disponibilă după 3 încercări

Provocare suplimentară

Exercițiu#python.m9.l2.e3
Încercări: 0Se încarcă…

Import `dataclass` from `dataclasses`. Create a dataclass `Point` containing two float coordinates `x` and `y`. Instantiate a point with `x=1.5` and `y=2.5` storing it in `p`. Finally, evaluate `p`.

Se încarcă editorul...
Afișează indiciu

Utilizați @dataclass deasupra clasei Point și declarați x: float și y: float.

Soluție disponibilă după 3 încercări