New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-43558: Add base class initialization to dataclass doc #25967
Conversation
This adds an sentence explaining that `super().__init__` ought to be called in the `__post_init__` function of dataclasses, and it adds a code example, since I felt it was clearer than a textual describtion.
Doc/library/dataclasses.rst
Outdated
| @@ -491,6 +491,22 @@ depend on one or more other fields. For example:: | |||
| def __post_init__(self): | |||
| self.c = self.a + self.b | |||
|
|
|||
| If the dataclass inherits from another class, which defines an :meth:`__init__` | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to start with something like: "The __init__ function generated by @dataclass does not call base class __init__ methods. If base class __init__ methods need to be called, it's common to do so in a __post_init__ method."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the feedback! I have adapted this text slightly in my last commit to reflect that the __init__ ought to be called if the base class has a non-default __init__ method, i.e. the one defined on object (this is also mentioned here in the docs). I was wondering if it should be mentioned that, when dealing with dataclasses, this is likely the case (I think that the generation of __init__ by @dataclass might obscure the presence of a non-default __init__).
|
|
||
| def __post_init__(self): | ||
| super().__init__(self.side, self.side) | ||
|
|
There was a problem hiding this comment.
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.
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
|
I have made the requested changes; please review again |
|
Thanks for making the requested changes! @ericvsmith: please review the changes made to this pull request. |
Doc/library/dataclasses.rst
Outdated
| @@ -491,6 +491,22 @@ 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 a non-default :meth:`__init__` method, it is | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know that anyone would know what "non-default __init__ method" means. I'd just leave it as "an __init__ method that needs to be called", or similar. Or maybe add words that say that in general, dataclass-generated __init__ methods to not need to be explicitly called, because the derived class __init__ takes care of initializing all fields.
|
I have made the requested changes; please review again |
|
Thanks for making the requested changes! @ericvsmith: please review the changes made to this pull request. |
|
|
||
| Note, however, that in general the dataclass-generated :meth:`__init__` methods not need to be | ||
| called, since the derived class will take care of initializing all fields. | ||
|
|
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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!
9cac499
to
004f915
Compare
|
I have made the requested changes; please review again |
|
Thanks for making the requested changes! @ericvsmith: please review the changes made to this pull request. |
Doc/library/dataclasses.rst
Outdated
| super().__init__(self.side, self.side) | ||
|
|
||
| Note, however, that in general the dataclass-generated :meth:`__init__` methods | ||
| not need to be called, since the derived dataclass will take care of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"not need to" isn't correct. Apologies if that was my error. Maybe simpler language is needed, like "... methods don't need to be called, since ...`.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, English is not my native tongue
|
|
||
| Note, however, that in general the dataclass-generated :meth:`__init__` methods not need to be | ||
| called, since the derived class will take care of initializing all fields. | ||
|
|
There was a problem hiding this comment.
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.
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
|
I have made the requested changes; please review again |
|
Thanks for making the requested changes! @ericvsmith: please review the changes made to this pull request. |
|
Thanks @dhoekstra2000 for the PR, and @ericvsmith for merging it |
|
GH-26018 is a backport of this pull request to the 3.10 branch. |
|
GH-26019 is a backport of this pull request to the 3.9 branch. |
pythonGH-25967) (cherry picked from commit 2a03172) Co-authored-by: dhoekstra2000 <douwe.hoekstra2512@gmail.com>
This adds an sentence explaining that
super().__init__oughtto be called in the
__post_init__function of dataclasses, andit adds a code example, since I felt it was clearer than a
textual describtion.
https://bugs.python.org/issue43558