Python 3.7's dataclasses reduce repetition in your class definitions.
Newcomers to Python often are surprised by how little code is required to accomplish quite a bit. Between powerful built-in data structures that can do much of what you need, comprehensions to take care of many tasks involving iterables, and the lack of getter and setter methods in class definitions, it's no wonder that Python programs tend to be shorter than those in static, compiled languages.
However, this amazement often ends when people start to define classes
in Python. True, the class definitions generally will be pretty
short. But the
__init__ method, which adds attributes to a new object,
tends to be rather verbose and repetitive—for example:
class Book(object): def __init__(self, title, author, price): self.title = title self.author = author self.price = price
Let's ignore the need for the use of
self, which is an outgrowth of
the LEGB (local, enclosing, global, builtins) scoping rules in
Python and which isn't going away. Let's also note that there is a
world of difference between the parameters
price and the attributes
What newcomers often wonder—and in the classes I teach, they often wonder
about this out loud—is why you need to make these assignments at
all. After all, can't
__init__ figure out that the three non-self
parameters are meant to be assigned to
self as attributes? If
Python's so smart, why doesn't it do this for you?
I've given several answers to this question through the years. One is that Python tries to make everything explicit, so you can see what's happening. Having automatic, behind-the-scenes assignment to attributes would violate that principal.
At a certain point, I actually came up with a half-baked solution to
this problem, although I did specifically say that it was un-Pythonic
and thus not a good candidate for a more serious implementation. In a
blog post, "Making Python's __init__ method magical", I proposed that
you could assign parameters to attributes automatically, using a
combination of inheritance and introspection. This was was a thought
experiment, not a real proposal. And yet, despite my misgivings and
the skeletal implementation, there was something attractive about not
having to write the same boilerplate
__init__ method, with the same
assignment of arguments to attributes.