Skip to content

Commit 3692677

Browse files
committed
Update dataclass documentation for new __eq__ behavior in 3.13 and add tests (#138991)
1 parent 08b07a2 commit 3692677

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

Doc/library/dataclasses.rst

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,16 @@ Module contents
103103
ignored.
104104

105105
- *eq*: If true (the default), an :meth:`~object.__eq__` method will be
106-
generated. This method compares the class as if it were a tuple
107-
of its fields, in order. Both instances in the comparison must
106+
generated.
107+
108+
.. versionchanged:: 3.13
109+
The generated ``__eq__`` method now compares each field individually (e.g., ``self.a == other.a and self.b == other.b``), rather than comparing tuples of fields as in previous versions.
110+
111+
This method compares the class by comparing each field in order. Both instances in the comparison must
108112
be of the identical type.
109113

114+
In Python 3.12 and earlier, the comparison was performed by creating tuples of the fields and comparing them (e.g., ``(self.a, self.b) == (other.a, other.b)``).
115+
110116
If the class already defines :meth:`!__eq__`, this parameter is
111117
ignored.
112118

Lib/test/test_dataclasses/__init__.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2597,6 +2597,45 @@ def __eq__(self, other):
25972597
self.assertEqual(C(1), 5)
25982598
self.assertNotEqual(C(1), 1)
25992599

2600+
def test_eq_field_by_field(self):
2601+
@dataclasses.dataclass
2602+
class Point:
2603+
x: int
2604+
y: int
2605+
2606+
p1 = Point(1, 2)
2607+
p2 = Point(1, 2)
2608+
p3 = Point(2, 1)
2609+
self.assertTrue(p1 == p2)
2610+
self.assertFalse(p1 == p3)
2611+
2612+
def test_eq_type_check(self):
2613+
@dataclasses.dataclass
2614+
class A:
2615+
x: int
2616+
2617+
@dataclasses.dataclass
2618+
class B:
2619+
x: int
2620+
2621+
a = A(1)
2622+
b = B(1)
2623+
self.assertFalse(a == b)
2624+
2625+
def test_eq_custom_field(self):
2626+
class AlwaysEqual(int):
2627+
def __eq__(self, other):
2628+
return True
2629+
2630+
@dataclasses.dataclass
2631+
class Foo:
2632+
x: AlwaysEqual
2633+
y: int
2634+
2635+
f1 = Foo(AlwaysEqual(1), 2)
2636+
f2 = Foo(AlwaysEqual(2), 2)
2637+
self.assertTrue(f1 == f2)
2638+
26002639

26012640
class TestOrdering(unittest.TestCase):
26022641
def test_functools_total_ordering(self):

0 commit comments

Comments
 (0)