Direct naar de hoofdinhoud
Module 9 · Les 2 van 434/36 in de cursus~12 min
Modulelessen (2/4)

dataclass: dataklassen zonder boilerplate

De @dataclass decorateur (dataclasses module) genereert automatisch __init__, __repr__ en __eq__ voor klassen waarvan de enige taak is vasthouden gegevens. Minder standaardtekst, duidelijkere code.

Zonder dataklasse (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)

Met dataklasse

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

Het patroon: velden declareren als klasseannotaties (name: type), eventueel met een standaardwaarde. @dataclass genereert de rest.

Standaard en standaard_fabriek

Python
from dataclasses import dataclass, field

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

bevroren=Waar: onveranderlijk

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

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

frozen dataklassen zijn ook hashbaar: u kunt ze gebruiken als dicteertoetsen of vaste elementen.

order=True: automatische vergelijkingen

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

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

Genereert __lt__, __le__, __gt__, __ge__ waarbij velden in de volgorde worden vergeleken ze werden verklaard.

Normale methoden

Dataklassen blijven reguliere klassen: u kunt methoden toevoegen.

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

Onveranderlijke en efficiënte dataklassen

U kunt een dataklasse onveranderlijk maken door het argument frozen=True door te geven aan de decorateur: @dataclass(frozen=True). Dit veroorzaakt een fout bij elke poging om attributen na instantiatie te muteren, waardoor instances veilig zijn voor gelijktijdige omgevingen of voor gebruik als woordenboeksleutels.

Probeer het zelf

Oefening#python.m9.l2.e1
Pogingen: 0Laden…

Maak een dataklasse `Book` aan met de velden `title: str` en `pages: int`. Instantieer het als `l = Book('Moby Dick', 635)`. Evalueer `l == Boek('Moby Dick', 635)`.

Editor laden…
Toon hint

@dataclass genereert __eq__ waarbij veld voor veld wordt vergeleken.

Oplossing beschikbaar na 3 pogingen

Oefening beoordelen

Oefening#python.m9.l2.e2
Pogingen: 0Laden…

Creëer een dataklasse `Basket` ​​met veld `items: list[str]` met default_factory=list. Instantieer `c1 = Basket()` en `c2 = Basket()`, voeg 'mela' toe aan c1.items. Evalueer `(c1.items, c2.items)` om te verifiëren dat ze NIET dezelfde lijst zijn.

Editor laden…
Toon hint

field(default_factory=list) garandeert een nieuwe lijst per exemplaar.

Oplossing beschikbaar na 3 pogingen

Extra uitdaging

Oefening#python.m9.l2.e3
Pogingen: 0Laden…

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`.

Editor laden…
Toon hint

Gebruik @dataclass boven de klasse Point en declareer x: float en y: float.

Oplossing beschikbaar na 3 pogingen