Dataclasses

When working with classes, a lot of boiler-plate code is often required: always __init__, __repr__, often __eq__, __lt__ for comparisons, often __hash__ when instances are used in sets or as dict keys, sometimes ‘neutral representation’ astuple, asdict as an export interface. Dataclasses does the job for you and are a huge time saver.

Note

It seems at first glance that class attributes are defined. However, this syntax in the context of a dataclass is called a field. It will actually create class instances with independent attributes. To explicitly define a class attribute, the typing.ClassVar type is required.

dataclasses_usage
 1from dataclasses import dataclass, field
 2from typing import ClassVar
 3
 4
 5@dataclass(order=True)  # allow ordering between instances
 6class Student:
 7    last_name: str
 8    first_name: str
 9    middle_names: list = field(default_factory=list)  # for a list instance attribute
10
11    id: int = field(init=False)  # not set by user, but automatically after init
12    nb_students: ClassVar[int] = 0  # a class attribute shared between instances
13
14    def __post_init__(self):  # optional, here used to fill automatically the "id"
15        self.id = self._generate_unique_id()
16
17    @classmethod
18    def _generate_unique_id(cls):
19        cls.nb_students += 1
20        return cls.nb_students
21
22
23def main() -> None:
24    student = Student("D", "a", ["b", "c"])  # using positional
25    other_student = Student(
26        first_name="a",
27        last_name="E",
28    )  # using keywords
29    print(student)
30    print(other_student)
31    print(student < other_student)
32    # the field order is the comparison order (lastname, then firstname, ...)
33
34
35if __name__ == "__main__":
36    main()