Dataclasses and Value Objects · practice
Build Alternative Constructors
A class normally has one way in: call it with the fields its constructor expects. Real data often arrives in another useful shape.
The class receives itself
@classmethod passes the class as the first cls.
cls(...) constructs through whichever class received the call. Hard-coding Duration(...) appears equivalent now, but an inherited constructor would then build the wrong class.
What is cls inside from_seconds?
Name meaningful ways in
An alternative constructor should name a recognizable source or use case:
@classmethod
def one_minute(cls):
return cls(1, 0)
Configuration classes benefit too:
@classmethod
def untimed(cls, title):
return cls(title, time_limit=0)
The caller reads the intention instead of repeating a collection of magic values.
Use an ordinary constructor for the general case and a class
Task
Add four alternative constructors using @classmethod.
Question.from_dict(record) reads "prompt", "answer", and "points". Question.simple(prompt, answer) builds a one-point question.
QuizConfig.practice(title) uses a pass mark of 0.5. QuizConfig.final_exam(title) uses 0.8 and a time limit of 3600.
Every cls(...), not by naming its class. The ordinary constructors keep their __post_init__ validation, so every alternative route must reject the same invalid values.