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: dataclasses __eq__ isn't logical
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.8, Python 3.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: eric.smith Nosy List: ccoleman, eric.smith, mark.dickinson
Priority: normal Keywords:

Created on 2022-02-13 16:35 by ccoleman, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (5)
msg413188 - (view) Author: Craig Coleman (ccoleman) Date: 2022-02-13 16:35
In a test, dataclasses generate an __eq__ function appears to be wrong.

@dataclass 
class C:
    pass
    
class K:
    pass

a = C()
b = C()
c = K()
d = K()

(a is b) # False
(a == b) # True # Incorrect, Why?
(c is d) # False
(c == d) # False # Correct

Using @dataclass(eq = False) for annotation of C would make (a == b) == False which I think is correct behaviour.
msg413190 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2022-02-13 17:44
Can you explain why you think the result of `a == b` should be `False` rather than `True`? By default, equality for dataclasses is structural equality, and `True` is the result that I'd expect here.

From the [docs](https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass) for `eq`: 

> If true (the default), an __eq__() method will be generated. This method compares the class as if it were a tuple of its fields, in order
msg413192 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2022-02-13 18:50
I agree with Mark. It's identical to:

>>> () == ()
True

As for the non-dataclass version, that's a normal object identity comparison if no __eq__ is defined: https://docs.python.org/3/reference/datamodel.html#object.__eq__ , third paragraph.
msg413243 - (view) Author: Craig Coleman (ccoleman) Date: 2022-02-14 18:21
Seems I learned a python lesson today.

I've put myself back in python school and done some reading on a) the code behind dataclasses, b) PEP 557 and c) the doc'n for __eq__.

After all the reading I've realised this I'd been making some assumptions about how __eq__ works which have now been corrected.  Thanks for your help.
msg413244 - (view) Author: Craig Coleman (ccoleman) Date: 2022-02-14 18:24
From  https://docs.python.org/3/reference/datamodel.html#object.__hash__

User-defined classes have __eq__() and __hash__() methods by default; with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y).

It doesn't work like that for tuples, NamedTuples nor dataclasses because their behaviour isn't expected to be a "user-defined class".
History
Date User Action Args
2022-04-11 14:59:56adminsetgithub: 90895
2022-02-14 18:24:08ccolemansetmessages: + msg413244
2022-02-14 18:21:09ccolemansetmessages: + msg413243
2022-02-14 18:08:52Dennis Sweeneysetstatus: open -> closed
resolution: not a bug
stage: resolved
2022-02-13 19:18:12eric.smithsetassignee: eric.smith
2022-02-13 18:50:00eric.smithsetmessages: + msg413192
2022-02-13 17:44:27mark.dickinsonsetnosy: + mark.dickinson
messages: + msg413190
2022-02-13 17:16:21AlexWaygoodsetnosy: + eric.smith
2022-02-13 16:35:46ccolemancreate