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)
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
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, 4Het patroon: velden declareren als klasseannotaties (name: type),
eventueel met een standaardwaarde. @dataclass genereert de rest.
Standaard en standaard_fabriek
from dataclasses import dataclass, field
@dataclass
class Articolo:
nome: str
prezzo: float = 0.0
tag: list[str] = field(default_factory=list)bevroren=Waar: onveranderlijk
@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
@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.
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.0Onveranderlijke 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
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)`.
Toon hint
@dataclass genereert __eq__ waarbij veld voor veld wordt vergeleken.
Oplossing beschikbaar na 3 pogingen
Oefening beoordelen
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.
Toon hint
field(default_factory=list) garandeert een nieuwe lijst per exemplaar.
Oplossing beschikbaar na 3 pogingen
Extra uitdaging
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`.
Toon hint
Gebruik @dataclass boven de klasse Point en declareer x: float en y: float.
Oplossing beschikbaar na 3 pogingen