W PEP 557 klasy danych są wprowadzane do standardowej biblioteki Pythona.
Używają @dataclass
dekoratora i mają być "zmiennymi nazwanymi krotkami z wartością domyślną", ale nie jestem pewien, czy rozumiem, co to właściwie oznacza i czym różnią się od zwykłych klas.
Czym dokładnie są klasy danych Pythona i kiedy najlepiej ich używać?
python
class
python-3.7
python-dataclasses
król Julian
źródło
źródło
namedtuple
s są niezmienne i nie mogą mieć wartości domyślnych dla atrybutów, podczas gdy klasy danych są zmienne i mogą je mieć.@dataclass
nie spowoduje dezintegracji witryny.namedtuples
MOŻE mieć wartości domyślne. Zajrzyj tutaj: stackoverflow.com/questions/11351032/…Odpowiedzi:
Klasy danych to zwykłe klasy, które są nastawione na przechowywanie stanu, a ponadto zawierają dużo logiki. Za każdym razem, gdy tworzysz klasę składającą się głównie z atrybutów, tworzysz klasę danych.
To, co
dataclasses
robi moduł, ułatwia tworzenie klas danych. Dba o dużo płyty kotłowej za Ciebie.Jest to szczególnie ważne, gdy klasa danych musi mieć możliwość mieszania; wymaga to zarówno
__hash__
metody, jak i__eq__
metody. Jeśli dodasz niestandardową__repr__
metodę ułatwiającą debugowanie, może to stać się dość rozwlekłe:Dzięki temu
dataclasses
możesz zredukować to do:Dekorator tej samej klasy mogą generować metod porównawczych (
__lt__
,__gt__
etc.) i uchwyt niezmienność.namedtuple
klasy są również klasami danych, ale są domyślnie niezmienne (a także są sekwencjami).dataclasses
są znacznie bardziej elastyczne pod tym względem i mogą być łatwo skonstruowane w taki sposób, że mogą pełnić taką samą rolę jaknamedtuple
klasa .PEP został zainspirowany
attrs
projektem , który może zrobić jeszcze więcej (w tym sloty, walidatory, konwertery, metadane itp.).Jeśli chcesz zobaczyć kilka przykładów, ostatnio użyłem
dataclasses
kilku moich rozwiązań Advent of Code , zobacz rozwiązania na dzień 7 , 8 , 11 i 20 .Jeśli chcesz używać
dataclasses
modułu w wersjach Pythona <3.7, możesz zainstalować backportowany moduł (wymaga 3.6) lub użyćattrs
projektu wspomnianego powyżej.źródło
@dataclass
generuje mniej więcej tę samą__init__
metodę, zquantity_on_hand
argumentem słowa kluczowego o wartości domyślnej. Podczas tworzenia instancjiquantity_on_hand
zawsze ustawi ona atrybut instancji. Tak więc mój pierwszy przykład bez klasy danych używa tego samego wzorca, aby powtórzyć działanie kodu wygenerowanego przez klasę danych.__post_init__
metodzie.Przegląd
Pytanie zostało rozwiązane. Jednak ta odpowiedź zawiera kilka praktycznych przykładów, które mogą pomóc w podstawowym zrozumieniu klas danych.
namedtuple
i inne .Oto, co oznacza to drugie zdanie:
namedtuple
lub zwykła klasa.W porównaniu z typowymi klasami oszczędzasz przede wszystkim na wpisywaniu standardowego kodu.
cechy
To jest przegląd funkcji klasy danych (TL; DR? Zobacz tabelę podsumowującą w następnej sekcji).
Co dostałeś
Oto funkcje, które domyślnie uzyskujesz z klas danych.
Atrybuty + reprezentacja + porównanie
Te wartości domyślne są zapewniane przez automatyczne ustawienie następujących słów kluczowych na
True
:Co możesz włączyć
Dodatkowe funkcje są dostępne, jeśli ustawiono odpowiednie słowa kluczowe
True
.Zamówienie
Zaimplementowano teraz metody porządkowania (przeciążanie operatorów:)
< > <= >=
, podobnie jak wfunctools.total_ordering
przypadku silniejszych testów równości.Hashable, Mutable
Chociaż obiekt jest potencjalnie zmienny (prawdopodobnie niepożądany), zaimplementowano skrót.
Hashable, Immutable
Hash jest teraz zaimplementowany, a zmiana obiektu lub przypisywanie atrybutów jest niedozwolone.
Ogólnie rzecz biorąc, obiekt jest haszowalny, jeśli jest
unsafe_hash=True
albofrozen=True
.Zobacz także oryginalną tablicę haszującą z dodatkowymi szczegółami.
Czego nie dostajesz
Aby uzyskać następujące funkcje, należy ręcznie zaimplementować specjalne metody:
Rozpakowanie
Optymalizacja
Rozmiar obiektu jest teraz zmniejszony:
W niektórych przypadkach
__slots__
poprawia również szybkość tworzenia instancji i uzyskiwania dostępu do atrybutów. Ponadto gniazda nie pozwalają na przypisanie domyślne; w przeciwnym razieValueError
podniesione jest a .Więcej informacji o automatach znajdziesz w tym poście na blogu .
Tabelka podsumowująca
+ Te metody nie są generowane automatycznie i wymagają ręcznej implementacji w klasie danych.
*
__ne__
nie jest potrzebne i dlatego nie jest realizowane .Dodatkowe funkcje
Po inicjalizacji
Dziedzictwo
Konwersje
Konwersja dataclass na krotki lub dict, rekurencyjnie :
Ograniczenia
Bibliografia
źródło
Ze specyfikacji PEP :
@dataclass
Generator dodaje metody do klasy, że chcesz inaczej zdefiniować siebie podobne__repr__
,__init__
,__lt__
, i__gt__
.źródło
Rozważ tę prostą klasę
Foo
Oto
dir()
wbudowane porównanie. Po lewej stronie znajduje sięFoo
dekorator bez @dataclass, a po prawej - dekorator @dataclass.Oto kolejna różnica, po użyciu
inspect
modułu do porównania.źródło