@dataclass
Dekorator, który na podstawie pól z adnotacjami typów generuje __init__, __repr__ i __eq__ klasy przechowującej dane.
- Zwraca
- Tę samą klasę uzupełnioną o wygenerowane metody.
Przykład
#from dataclasses import dataclass, field
@dataclass
class Student:
name: str
world: int
points: int = 0
badges: list[str] = field(default_factory=list)
ania = Student("Ania", 7)
ania.points += 40
ania.badges.append("Start")
print(ania)
print(ania == Student("Ania", 7, 40, ["Start"]))
print(Student("Kuba", 2))Definicja i zastosowanie
#Dekorator @dataclass z modułu dataclasses usuwa z klas przechowujących dane powtarzalny kod. Wystarczy wypisać pola z adnotacjami typów (name: str), a dekorator wygeneruje __init__ z parametrami w tej samej kolejności, czytelny __repr__ oraz __eq__, który porównuje obiekty pole po polu.
Pola mogą mieć wartości domyślne (points: int = 0), ale pola bez wartości domyślnej muszą stać przed nimi. Listę, słownik czy inny zmienny obiekt jako wartość domyślną podaje się przez field(default_factory=list), dzięki czemu każdy obiekt dostaje własną kopię. Dodatkowe kroki po utworzeniu obiektu, np. walidację albo wyliczenie pomocniczego pola, umieść w metodzie __post_init__.
Parametry dekoratora zmieniają zachowanie klasy, np. frozen=True blokuje zmiany pól, a order=True dodaje porównania < i >. Funkcja asdict() zamienia obiekt na słownik, np. do zapisu w JSON, a replace() tworzy kopię ze zmienionymi polami. Adnotacje typów nie są sprawdzane w czasie działania programu, służą edytorom i narzędziom takim jak mypy.
Składnia
#from dataclasses import dataclass, field
@dataclass
class Nazwa:
pole: typ
pole_z_domyslna: typ = wartosc
lista: list[typ] = field(default_factory=list)
@dataclass(frozen=True, order=True)
class Inna:
...Parametry
#frozen
bool, domyślnie False
GdyTrue, zmiana pola zgłaszaFrozenInstanceError, a obiekty mogą być kluczami słowników i elementami zbiorów.order
bool, domyślnie False
Dodaje operatory<,<=,>i>=, które porównują pola po kolei, tak jak krotki.slots
bool, domyślnie False
Tworzy klasę z__slots__: obiekty zajmują mniej pamięci, a przypisanie do nieistniejącego pola zgłasza błąd.kw_only
bool, domyślnie False
Wymusza podawanie wszystkich pól po nazwie przy tworzeniu obiektu.
Więcej przykładów
#from dataclasses import dataclass, field
@dataclass(frozen=True, order=True)
class Result:
points: int
name: str = field(compare=False)
results = [Result(78, "Kuba"), Result(92, "Ania"), Result(85, "Ola")]
print([r.name for r in sorted(results, reverse=True)])
best = max(results)
try:
best.points = 100
except AttributeError as error:
print(type(error).__name__, error)field(compare=False) wyłącza pole z porównań, więc wyniki są sortowane tylko po punktach.
from dataclasses import dataclass, field
@dataclass
class Exercise:
number: str
exp: int
world: int = field(init=False)
def __post_init__(self):
if self.exp < 0:
raise ValueError("EXP nie może być ujemne")
self.world = int(self.number.split("_")[0])
task = Exercise("7_3", 15)
print(task.world)
print(task)import json
from dataclasses import asdict, dataclass, replace
@dataclass
class Course:
title: str
modules: int
premium: bool = False
python = Course("Python", 12)
advanced = replace(python, title="Python zaawansowany", premium=True)
print(advanced)
print(asdict(python))
print(json.dumps(asdict(advanced), ensure_ascii=False))Dobre praktyki
#- Pola ze zmiennymi wartościami domyślnymi twórz przez
field(default_factory=list). Zapisbadges: list = []zgłosiValueErrorjuż przy definicji klasy. - Typy w adnotacjach nie są sprawdzane, więc
Student(name=123, world="siedem")utworzy obiekt bez błędu. Do walidacji użyj__post_init__albo biblioteki pydantic. - Obiekty z
frozen=Truemożna bezpiecznie współdzielić między częściami programu, bo nikt ich przypadkiem nie zmieni.
Powiązane hasła
#- classDefiniuje klasę: szablon obiektów łączący dane i funkcje, które na nich działają.
- __init__()Metoda wywoływana automatycznie przy tworzeniu obiektu. Zapisuje w nim dane początkowe, czyli atrybuty.
- __str__() i __repr__()Metody określające tekstowy wygląd obiektu: czytelny dla użytkownika (__str__) i techniczny dla programisty (__repr__).
- Metody specjalneMetody z podwójnymi podkreślnikami, dzięki którym obiekty działają z operatorami ==, <, +, in oraz z funkcją len().
- typingAdnotacje typów: opis, jakich wartości oczekuje funkcja i co zwraca. Sprawdzają je edytory i narzędzia takie jak mypy.
- collections.namedtupleTworzy krotki z nazwanymi polami: dane odczytasz przez student.points zamiast student[2], a obiekt pozostaje niezmienny.
Widzisz błąd albo brakuje przykładu? Napisz do nas.