This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: dataclass __foo__ methods inheritance is not working
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: eric.smith Nosy List: colin-b, eric.smith, xtreak
Priority: normal Keywords:

Created on 2019-07-02 13:44 by colin-b, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
inheritance_dataclass_issue.py colin-b, 2019-07-02 13:44 Sample
Messages (4)
msg347142 - (view) Author: Colin (colin-b) * Date: 2019-07-02 13:44
Hi,

When using inheritance with dataclass, "standard" instance methods that are provided with a default behavior thanks to dataclass are not overridable using inheritance.

Please see the sample below (or the attached file):

import dataclasses


@dataclasses.dataclass
class A:
    def __eq__(self, other):
        return True


@dataclasses.dataclass
class B(A):
    pass


print(A() == 1) # Returns True as expected
print(B() == 1) # Returns False instead of True as expected via inheritance


Thanks again
msg347146 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python committer) Date: 2019-07-02 15:18
https://docs.python.org/3/library/dataclasses.html#inheritance

> When the dataclass is being created by the dataclass() decorator, it looks through all of the class’s base classes in reverse MRO (that is, starting at object) and, for each dataclass that it finds, adds the fields from that base class to an ordered mapping of fields. After all of the base class fields are added, it adds its own fields to the ordered mapping. All of the generated methods will use this combined, calculated ordered mapping of fields. Because the fields are in insertion order, derived classes override base classes.

I think here in the example __eq__ is defined in A and is inherited by B but since eq=False is not explicitly defined in the decorator the dataclass will use it's own definition of eq and override it at [0] . So using eq=False will work as expected. I propose closing this as not a bug. 


import dataclasses


@dataclasses.dataclass
class A:
    def __eq__(self, other):
        return True


@dataclasses.dataclass(eq=False) # By default eq=True
class B(A):
    pass


print(A() == 1) # Returns True as expected
print(B() == 1) # Returns True since inherited A.__eq__ is not overriden with eq=False


Output

./python.exe ../backups/bpo37485.py
True
True

[0] https://github.com/python/cpython/blob/7cb9204ee1cf204f6f507d99a60f7c5bb359eebb/Lib/dataclasses.py#L922
msg347149 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2019-07-02 16:22
I agree with xtreak that this works as designed and isn't a bug.
msg347150 - (view) Author: Colin (colin-b) * Date: 2019-07-02 16:36
I personally find it easier to understand if inheritance is the default behaviour, instead of having to explicitly disable a feature that's seems primarily designed for non-herited dataclasses.

But whatever suits best the community :-)

Thanks for the quick reply
History
Date User Action Args
2022-04-11 14:59:17adminsetgithub: 81666
2019-07-02 16:36:56colin-bsetmessages: + msg347150
2019-07-02 16:22:27eric.smithsetstatus: open -> closed
messages: + msg347149

assignee: eric.smith
resolution: not a bug
stage: resolved
2019-07-02 15:18:04xtreaksetnosy: + xtreak
messages: + msg347146
2019-07-02 14:00:15xtreaksetnosy: + eric.smith
2019-07-02 13:44:03colin-bcreate