#257: Less Boilerplate Code With Data Classes
Creating DTOs with NamedTuple was a nice way to create read-only structures to pass between functions. But not always is a read-only structure the right tool for the job. Let us look how we can create changeable structures like classes with ease.
The problem
Writing classes in Python requires a lot of recuring boilerplate code:
>>> quick = Book("The Quick Python Book", "Naomi Ceder", 550)
>>> quick
<__main__.Book object at 0x00000246BBD42990>
Yes, we can write classes that way and many developers do it without a second thought. But I do not like it and need a nicer approach that is more like Pydantic models. Luckily for me, there is such an approach directly built into Python.
Data classes
Data classes are part of Python since version 3.7 and reduce the boilerplate code by a lot. If we use the @dataclass decorator, we can write the class from above with just these lines:
I like this approach a lot better. Not only do we skip the __init__ method, we get most of the helpful special methods for free and with useful implementations:
>>> quick = Book("The Quick Python Book", "Naomi Ceder", 550)
>>> quick
Book(title='The Quick Python Book', author='Naomi Ceder', pages=550)
If we want to add our own methods, we can do that as we would with regular classes:
>>> quick = Book("The Quick Python Book", "Naomi Ceder", 550)
>>> quick.csv()
'The Quick Python Book, Naomi Ceder, 550'
Default values
If we want to set default values, we can do so in our property list:
We get now a 1 as value even when we do not set it:
Yet we can still set a value if we want to:
Unchangeable data classes
If we want to have classes where we cannot change the values, we do not need to go back to named tuples. Instead, we can pass frozen=True to the decorator:
If we now try to change the values, we get a FrozenInstanceError:
>>> start = Point(2,4)
>>> start
Point(x=2, y=4)
>>> start.x = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 4, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'x'
Next
With the @dataclasses decorator we can save a lot of boilerplate code and still get the whole flexibility of classes in Python. I find this a massive improvement that I will use a lot.
Next week we work a bit with XML and fix the RSS feed of this blog.