hayaliv / Hi! Python / Level 2
Dataclasses
@dataclass writes __init__, __repr__ and __eq__ for you, so a record like Example(input, label) takes a few lines.
Think of it like this
A dataclass is like a printed form with labelled boxes. You only name the boxes (input, label). The print shop adds the border, the box numbers and the rule for comparing two filled forms.
Where the analogy stops being true. A paper form can reject a wrong entry at the desk, but a dataclass accepts any value you put in a box.
What to know
- A dataclass is a normal class with the @dataclass decorator on top.
- You list the fields as annotated class variables, such as input: str.
- The decorator generates __init__, __repr__ and __eq__ for you. The example output shows all three at work.
- A field can have a default value, like label: str = "unknown".
- For a list default, use field(default_factory=list). The third predict item shows each instance gets its own list.
- With frozen=True, assigning to a field raises an exception.
- A dataclass does not check types: the last line of the example stores the number 5 as a label.
Example
from dataclasses import dataclass, field
@dataclass
class Example:
input: str
label: str = "unknown"
tags: list[str] = field(default_factory=list)
a = Example("Call me Tuesday", "meeting_request")
b = Example("Call me Tuesday", "meeting_request")
print(a)
print(a == b)
print(Example("hello"))
print(Example("oops", 5))
It prints:
Example(input='Call me Tuesday', label='meeting_request', tags=[])
True
Example(input='hello', label='unknown', tags=[])
Example(input='oops', label=5, tags=[])
Predict, then check
1. What does this print?
from dataclasses import dataclass
@dataclass
class Pair:
text: str
label: str
print(Pair("hi", "x") == Pair("hi", "x"))
print(Pair("hi", "x") == Pair("hi", "y"))Show the answer
True
FalseThe generated __eq__ compares the fields in order, so equal fields give True and one different field gives False.
2. What does this print?
from dataclasses import dataclass
@dataclass(frozen=True)
class Pair:
text: str
label: str
p = Pair("hi", "x")
try:
p.label = "y"
except Exception as err:
print(type(err).__name__)
print(p.label)Show the answer
FrozenInstanceError
xAssigning to a field of a frozen dataclass raises FrozenInstanceError. The except block prints its name and the label stays unchanged.
3. What does this print?
from dataclasses import dataclass, field
@dataclass
class Box:
items: list = field(default_factory=list)
a = Box()
b = Box()
a.items.append(1)
print(a.items, b.items)Show the answer
[1] []default_factory builds a fresh list for every new Box, so changing a.items does not touch b.items.
4. What does this print? (The class is defined inside try.)
from dataclasses import dataclass
try:
@dataclass
class Bad:
flags: list = []
except ValueError as err:
print(err)Show the answer
mutable default <class 'list'> for field flags is not allowed: use default_factoryPython refuses a plain list as a field default when @dataclass runs, and the ValueError message tells you to use default_factory.
Try it
Write a dataclass Reply with a text field (str), a label field (str, default "unknown") and a flags field (list of str, empty by default, a separate list for each instance).
class Reply:
pass
Show a solution
from dataclasses import dataclass, field
@dataclass
class Reply:
text: str
label: str = "unknown"
flags: list[str] = field(default_factory=list)Common mistake
Do not write flags: list = [] inside a dataclass. Python refuses it with a ValueError, as the fourth predict item shows. Use field(default_factory=list) instead.
In a small-language-model project
In a fine-tuning project you usually load many labelled replies. An Example(input, label) dataclass gives each record a readable print and an == check for free. Because nothing checks types, validate labels yourself (see the Exceptions lesson).
Sources
Each quote below appears word for word on the cited page of the official Python documentation (version 3.12).
This function is a decorator that is used to add generated special methods to classes
docs.python.org/3.12/library/dataclasses.html — @dataclass is a decorator that adds generated special methods to classes.This method compares the class as if it were a tuple of its fields, in order.
docs.python.org/3.12/library/dataclasses.html — The generated __eq__ compares fields in order.it must be a zero-argument callable that will be called when a default value is needed for this field.
docs.python.org/3.12/library/dataclasses.html — default_factory is a zero-argument callable used to make a default value.If true (the default is False ), assigning to fields will generate an exception.
docs.python.org/3.12/library/dataclasses.html — frozen=True makes assigning to fields raise an exception.nothing in @dataclass examines the type specified in the variable annotation.
docs.python.org/3.12/library/dataclasses.html — @dataclass does not examine the type in an annotation (with two documented exceptions).