De decorator @dataclass is een van de hulpmiddelen die zijn geïntroduceerd in Python 3.7 om sjablooncode te verkorten bij het maken van eenvoudige dataclassen. Dankzij type-annotaties genereert Python automatisch de methodes __init__, __repr__, __eq__ en anderen.
Achtergrond:
Voor de introductie van dataclass schreven ontwikkelaars sjabloonklassen handmatig, implementerende constructeurs, vergelijkingsmethodes, repr, en gingen daarna vaak over op named tuples of bibliotheken zoals attrs. De introductie van @dataclass heeft dit proces gestandaardiseerd en vereenvoudigd.
Probleem:
Sjablooncode (boilerplate), duplicatie van code in constructeurs en vergelijkingsmethodes leidde vaak tot fouten en maakte het onderhoud van grote applicaties ingewikkeld.
Oplossing:
Het gebruik van type-annotaties en de speciale decorator @dataclass maakt het mogelijk om automatisch alle benodigde methodes in de klasse te genereren.
Voorbeeldcode:
from dataclasses import dataclass @dataclass class Point: x: int y: int p1 = Point(10, 20) p2 = Point(10, 20) print(p1 == p2) # True, automatisch gegenereerd __eq__ print(p1) # Point(x=10, y=20), automatisch gegenereerd __repr__
Belangrijke kenmerken:
Verandert @dataclass het gedrag van overerving (kenmerken bij overerving)?
Ja. Bij het overerven van dataclasses is het belangrijk op te merken: de velden van de basisklasse komen eerder dan die van de subklasse, en er kunnen fouten optreden bij conflicten in constructeurs/argumentvolgorde. Als er in de basis- en subklasse velden met dezelfde naam zijn, zal de laatste de vorige overschrijven.
Kun je in een dataclass veranderlijke standaardwaarden voor velden gebruiken?
Nee, je kunt dergelijke objecten (bijvoorbeeld een lijst) niet direct als standaard gebruiken — je moet field(default_factory=list) gebruiken. Anders delen alle instanties van de klasse dezelfde collectie.
Voorbeeld:
from dataclasses import dataclass, field @dataclass class User: values: list = field(default_factory=list)
Is @dataclass snel voor alle scenario's? Is het geschikt voor optimale opslag van grote datalijsten?
Nee. Een dataclass is niet de meest efficiënte optie voor geheugoptimalisatie. Voor het opslaan van miljoenen objecten is het beter om __slots__, namedtuple of speciale structuren te gebruiken - dataclass voegt extra velden toe en bespaart geen geheugen zoals slots. Het kan worden gecombineerd door de parameter slots=True door te geven (Python 3.10+), of handmatig slots te gebruiken.
@dataclass class Cart: items: list = [] # fout! c1 = Cart() c2 = Cart() c1.items.append("a") print(c2.items) # ['a'] — alle Cart-instanties delen dezelfde lijst
Voordelen:
Nadelen:
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) # []
Voordelen:
Nadelen:
field(default_factory=...) (wat aparte studie vereist).