Direkt zum Hauptinhalt springen
eLearner.app
Modul 9 · Lektion 2 von 434/36 im Kurs~12 min
Lektionen des Moduls (2/4)

dataclasses: Datenklassen ohne Boilerplate

Der Dekorator @dataclass (Modul dataclasses) generiert automatisch __init__, __repr__ und __eq__ für Klassen, deren einzige Aufgabe es ist, Daten zu speichern. Weniger Boilerplate, klarerer Code.

Ohne Dataclass (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)

Mit 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

Das Muster: Deklariere Felder als Klassenannotationen (name: type), optional mit einem Standardwert. @dataclass generiert den Rest.

Standardwerte und 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=True: unveränderlich

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

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

Mit frozen deklarierte Dataclasses sind auch hashbar (hashable): Du kannst sie als Dictionary-Schlüssel oder Set-Elemente verwenden.

order=True: automatische Vergleiche

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

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

Generiert __lt__, __le__, __gt__, __ge__, indem die Felder in der Reihenfolge ihrer Deklaration verglichen werden.

Normale Methoden

Dataclasses bleiben normale Klassen: Du kannst Methoden hinzufügen.

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

Unveränderliche und effiziente Dataclasses

Du kannst eine Dataclass unveränderlich machen, indem du dem Dekorator das Argument frozen=True übergibst: @dataclass(frozen=True). Dies führt zu einem Fehler bei jedem Versuch, Attribute nach der Instanziierung zu verändern, wodurch Instanzen für nebenläufige Umgebungen oder als Dictionary-Schlüssel geeignet sind.

Probiere es aus

Übung#python.m9.l2.e1
Versuche: 0Wird geladen…

Erstelle eine Dataclass `Book` mit den Feldern `title: str` und `pages: int`. Instanziiere sie als `l = Book('Moby Dick', 635)`. Evaluiere `l == Book('Moby Dick', 635)`.

Editor wird geladen…
Hinweis anzeigen

@dataclass generiert __eq__, indem Feld für Feld verglichen wird.

Lösung nach 3 Versuchen verfügbar

Wiederholungsübung

Übung#python.m9.l2.e2
Versuche: 0Wird geladen…

Erstelle eine Dataclass `Basket` mit dem Feld `items: list[str]` und default_factory=list. Instanziiere `c1 = Basket()` und `c2 = Basket()`, hänge 'mela' an c1.items an. Evaluiere `(c1.items, c2.items)`, um zu überprüfen, dass es sich NICHT um dieselbe Liste handelt.

Editor wird geladen…
Hinweis anzeigen

field(default_factory=list) garantiert eine neue Liste pro Instanz.

Lösung nach 3 Versuchen verfügbar

Zusätzliche Herausforderung

Übung#python.m9.l2.e3
Versuche: 0Wird geladen…

Importiere `dataclass` aus `dataclasses`. Erstelle eine Dataclass `Point` mit zwei float-Koordinaten `x` und `y`. Instanziiere einen Punkt mit `x=1.5` und `y=2.5` und speichere ihn in `p`. Evaluiere schließlich `p`.

Editor wird geladen…
Hinweis anzeigen

Verwende @dataclass über der Klasse Point und deklariere x: float und y: float.

Lösung nach 3 Versuchen verfügbar