Class inheritance in Python 3.7 dataclasses
To employ inheritance in Python dataclasses, the @dataclass
decorator is simply applied to both the base and derived (child) classes. The derived class inherits the base class's attributes and can add its own. The fundamental code example is as follows:
Here, the Derived
class inherits the common
field from the Base
, augmenting it with the specific
field. The beauty of dataclass inheritance is well illustrated in this example.
Unveiling the intricacies of inheritance
For a comprehensive grasp of inheritance in Python's dataclasses, it's critical to peel back the curtain and dig into the details:
Field declaration and the MRO
In dataclasses, always define fields via type hints for explicit attribute descriptions. Be cognizant of the Method Resolution Order (MRO)
. Non-default fields should precede those having defaults to elude the dreaded TypeError
triggered by default arguments following non-default ones:
Implement post_init
To enable introspection of fields or validation after initialization, the __post_init__
can be invoked in your class, which is executed post __init__
:
Inheritance dance with field()
For base class fields possessing default values, the field()
function should be harnessed to avert initialization idiosyncrasies. It ensures fields hit the dance floor (dataclass) in the right order and have their defaults assigned properly.
Diving deeper: Advanced concepts
For dealing with complex scenarios like a pro, allow me to introduce you to Praveen Kulkarni's extended answer, Eric Smith's enlightening blog and the wonders of the attrs library:
Keyword-only fields
Starting from Python 3.10, setting kw_only=True
with @dataclass
lets you define keyword-only fields. For those on Python 3.7, Eric Smith's blog provides a handy solution to achieve functionality similar to keyword-only fields:
Handling multiple inheritance
Aim to neatly separate base classes for correct MRO order to prevent bumping into issues with field definition while inheriting from multiple bases:
Embrace InitVar and factory methods
InitVar can prove helpful for additional parameters that are required at initialization but don't eventually turn into class fields. Moreover, factory methods can maintain a neat and clean class signature:
Was this article helpful?