When a Class Helps and When a Dict Is Enough
Once you know classes, it is tempting to make everything one. Often a dictionary, or a plain function, is simpler and better, and experienced programmers reach for classes less often than beginners expect. This page gives an honest rule of thumb for choosing, so classes appear where they earn their place.
Think of a shoebox, a labelled filing folder and a locked cash box. Each is the right container for something, and you would not keep old receipts in the cash box. The containers in a program deserve the same judgment.
A Dictionary Is Enough When
The data is passed along without rules of its own, or it is loaded from JSON and saved back to JSON, or it only ever lives for a few lines. The rows from csv.DictReader in Chapter 7 were dictionaries, and that was exactly right: they were read, converted and totalled, and nothing more.
A Dataclass Helps When
The same shape of record appears in several parts of a program, and you want a mistake in it to be caught. The difference shows at the moment a record is created. Misspell a key in a dictionary and it is simply accepted as a new key; nothing complains, and the mistake surfaces much later, if at all. Misspell a field when creating a dataclass object and Python refuses at once, and Python 3.15 even suggests the right name.
from dataclasses import dataclass @dataclass class Book: title: str author: str pages: int record = {"title": "Dune", "author": "Frank Herbert", "pages": 412} record["titel"] = "Dune Messiah" print(record) Book(titel="Dune", author="Frank Herbert", pages=412)
{'title': 'Dune', 'author': 'Frank Herbert', 'pages': 412, 'titel': 'Dune Messiah'}
Traceback (most recent call last):
File "/Users/you/python-course/typo.py", line 15, in <module>
Book(titel="Dune", author="Frank Herbert", pages=412)
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: Book.__init__() got an unexpected keyword argument 'titel'. Did you mean 'title'?
To be fair to dictionaries, the protection has limits. Assigning a misspelled field to an existing dataclass object, as in book.titel = "...", with title misspelled, is also accepted silently, unless the class is declared with an option called slots, which is beyond this book. The dataclass catches mistakes where records are made, which is where most of them happen.
A Class with Methods Helps When
The data comes with rules that must always hold. A bank balance that must never go below zero is the classic example: put the rule inside a withdraw method, and no part of the program can forget it. When the rules live in one place, next to the data they protect, they cannot drift apart.
A Function Is Enough When
There is behaviour but no lasting data. A conversion, a calculation, a check: calculate_tip(bill, percent) does not need to be a class. A class with one method and nothing to remember is usually a function that got dressed up.
Converting Between Them
The two worlds meet easily. The asdict function from the dataclasses module turns a dataclass object into a dictionary, ready for JSON. Going the other way, two stars in front of a dictionary spread its keys out as keyword arguments, so Book(**data) builds a Book from a dictionary with matching keys, and still catches a misspelled one.
from dataclasses import asdict, dataclass @dataclass class Book: title: str author: str pages: int dune = Book("Dune", "Frank Herbert", 412) data = asdict(dune) print(data) print(Book(**data))
{'title': 'Dune', 'author': 'Frank Herbert', 'pages': 412}
Book(title='Dune', author='Frank Herbert', pages=412)
- "Professional code uses classes for everything." Good code uses the simplest structure that does the job. Many excellent programs have few classes.
- "Dictionaries are the beginner's option." They are the right option for a great deal of data, at every level of experience.
- "A dataclass catches every misspelled field." It catches them when a record is created. Assigning a misspelled field later is accepted unless the class uses slots.
- "Classes make programs faster." They make some programs clearer. Speed is not the reason to use one.
- Choosing the simplest structure keeps programs small and easy to read, which matters more than any single clever design.
- The same judgment applies in every language that has classes, which is almost all of them.
Knowledge Check
What happens when you add the key "titel" to a dictionary by mistake?
- It is accepted silently as a new key
- Python raises a KeyError straight away
- Python corrects it to title automatically
- The dictionary refuses keys it has not seen
What happens with Book(titel="Dune", ...) for a dataclass with a title field?
- The misspelled field is stored alongside the others
- A TypeError, which in 3.15 suggests the name title
- The title field is quietly left as None
- Python renames titel to title for you and carries on
When is a class with methods the right choice?
- Whenever the program is longer than a hundred lines
- Whenever data is loaded from a JSON file
- When the data has rules that must always hold
- Whenever a function needs more than two parameters
What does asdict(book) give?
- A JSON string, ready to be written to a file
- A copy of the Book object with the same fields
- A list of the book's field names, in order
- A dictionary of the book's fields and values
You got correct