Der Dekorator @dataclass ist eines der Werkzeuge, die in Python 3.7 eingeführt wurden, um den Boilerplate-Code bei der Erstellung einfacher Datenspeicherklassen zu reduzieren. Dank der Typannotationen erstellt Python automatisch die Methoden __init__, __repr__, __eq__ und andere.
Geschichte der Frage:
Vor der Einführung von dataclass schrieben Entwickler Boilerplate-Klassen manuell, implementierten Konstruktoren, Vergleichsmethoden, repr und wechselten häufig dann zu benannten Tupeln oder Bibliotheken wie attrs. Die Einführung von @dataclass standardisierte und vereinfachte diesen Prozess.
Problem:
Boilerplate-Code und die Wiederholung von Konstruktor- und Vergleichsmethoden führten häufig zu Fehlern und erschwerten die Wartung großer Anwendungen.
Lösung:
Die Verwendung von Typannotationen und des speziellen Dekorators @dataclass ermöglicht es, automatisch alle erforderlichen Methoden in der Klasse zu generieren.
Beispielcode:
from dataclasses import dataclass @dataclass class Point: x: int y: int p1 = Point(10, 20) p2 = Point(10, 20) print(p1 == p2) # True, automatisch generiertes __eq__ print(p1) # Point(x=10, y=20), automatisch generiertes __repr__
Wesentliche Merkmale:
Ändert @dataclass das Verhalten der Vererbung (eigenschaften bei der vererbung)?
Ja. Bei der Vererbung von dataclass-Klassen ist besondere Vorsicht geboten: Die Felder der Basisklasse stehen vor den Feldern der abgeleiteten Klasse, und es können auch Fehler bei Konflikten von Konstruktoren/Argumentreihenfolge auftreten. Wenn in der Basisklasse und der abgeleiteten Klasse Felder mit denselben Namen vorhanden sind, wird das letzte das vorherige überschreiben.
Kann man in dataclass veränderliche Standardwerte für Felder verwenden?
Nein, man kann solche Objekte (z. B. Listen) nicht direkt als Standard verwenden — man muss field(default_factory=list) verwenden. Andernfalls teilen sich alle Instanzen der Klasse dieselbe Sammlung.
Beispiel:
from dataclasses import dataclass, field @dataclass class User: values: list = field(default_factory=list)
Ist @dataclass für alle Szenarien schnell? Eignet es sich für die optimale Speicherung großer Datenmengen?
Nein. Dataclass ist nicht die effizienteste Option zur Speicheroptimierung. Für die Speicherung von Millionen von Objekten ist es besser, __slots__, namedtuple oder spezielle Strukturen zu verwenden — dataclass fügt Dienstfelder hinzu und spart nicht so viel Speicher wie Slots. Man kann kombinieren, indem man den Parameter slots=True (Python 3.10+) übergibt oder manuell slots verwendet.
@dataclass class Cart: items: list = [] # Fehler! c1 = Cart() c2 = Cart() c1.items.append("a") print(c2.items) # ['a'] — alle Cart teilen sich die gleiche Liste
Vorteile:
Nachteile:
from dataclasses import dataclass, field @dataclass class Cart: items: list = field(default_factory=list) c1 = Cart() c2 = Cart() c1.items.append("a") print(c2.items) # []
Vorteile:
Nachteile:
field(default_factory=...) Bescheid wissen (was ein separates Lernen erfordert).