Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Doc/library/dataclasses.rst
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,27 @@ depend on one or more other fields. For example::
def __post_init__(self):
self.c = self.a + self.b

The :meth:`__init__` method generated by :func:`dataclass` does not call base
class :meth:`__init__` methods. If the base class has an :meth:`__init__` method
that has to be called, it is common to call this method in a
:meth:`__post_init__` method::

@dataclass
class Rectangle:
height: float
width: float

@dataclass
class Square(Rectangle):
side: float

def __post_init__(self):
super().__init__(self.side, self.side)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a great example.

Note, however, that in general the dataclass-generated :meth:`__init__` methods
don't need to be called, since the derived dataclass will take care of
initializing all fields of any base class that is a dataclass itself.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. How about instead of "the derived class", use "the derived dataclass"? I'm trying to draw the distinction that if a non-dataclass is derived from a dataclass, then the base class's __init__ should in fact be called.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand PEP 557 correctly, the __init__ method needs to be called if a dataclass inherits from a non-dataclass or if a non-dataclass inherits from a dataclass. I have tried to reflect this in the new wording.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand PEP 557 correctly, the __init__ method needs to be called if a dataclass inherits from a non-dataclass or if a non-dataclass inherits from a dataclass. I have tried to reflect this in the new wording.

If a dataclass inherits from a non-dataclass, then it's probably that the base non-dataclass's __init__ does need to be called. That's what __post_init__ is for, among other uses.

If a non-dataclass inherits from a dataclass, then the non-dataclass most likely does need to call the dataclass's __init__.

It's only the case where a dataclass inherits from a dataclass that the base class's __init__ most likely doesn't need to be called. I say "most likely" because you could construct examples where it does need to be called, if the base dataclass's __post_init__ does some processing. But it's probably too complex to mention that here, I'm just mentioning it here to help you understand the issue. Apologies if I'm not being helpful.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very helpful! Thank you!

See the section below on init-only variables for ways to pass
parameters to :meth:`__post_init__`. Also see the warning about how
:func:`replace` handles ``init=False`` fields.
Expand Down
1 change: 1 addition & 0 deletions Misc/ACKS
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,7 @@ David Hobley
Tim Hochberg
Benjamin Hodgson
Joerg-Cyril Hoehle
Douwe Hoekstra
Gregor Hoffleit
Chris Hoffman
Tim Hoffmann
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add the remark to :mod:`dataclasses` documentation that the :meth:`__init__` of any base class
has to be called in :meth:`__post_init__`, along with a code example.