Dataclasses and Value Objects · practice
Build Mutable Defaults Safely
A number can be shared safely as a default because it cannot be changed. A
Dataclasses refuse the tempting version:
from dataclasses import dataclass
@dataclass
class QuizAttempt:
learner: str
responses: list = []
If one list were created when the class was defined, every attempt would receive the same object.
Ask for a new list each time
Use field(default_factory=list):
eq=False turns off generated QuizAttempt represents one attempt, so two separate attempts should remain unequal even when their learner and responses match. This preserves the entity identity from Chapter 7.
The factory is the list, not a call to it. The generated constructor calls that function each time it needs a default, producing a fresh list for the new instance.
Why is this written default_factory=list rather than default_factory=list()?
The bug can hide
Shared
Use a factory for mutable per-object starting state:
| Starting value | Field definition |
|---|---|
| New empty list | field(default_factory=list) |
| New empty | field(default_factory=dict) |
| Number or | A direct default |
The exercise gives both a configuration and an attempt their own lists. The grader creates pairs and changes only one member of each pair.
Task
Give each
QuizConfig has a required title and tags starting as a new empty
QuizAttempt has a required learner and responses starting as a new empty list per attempt. Use eq=False because attempts are identity-based entities.
Use field(default_factory=list) for both lists. The grader changes one object and verifies the other remains empty.