https://github.com/python/cpython/commit/402668b2b1a63a2b3cfd7a2ede07f6786f9beb8e
commit: 402668b2b1a63a2b3cfd7a2ede07f6786f9beb8e
branch: main
author: Aniket <[email protected]>
committer: vstinner <[email protected]>
date: 2026-06-11T17:15:29Z
summary:

gh-138991: Update dataclass documentation for new eq behavior in Python 3.13 
(#139007)

And add tests.

Co-authored-by: Victor Stinner <[email protected]>

files:
M Doc/library/dataclasses.rst
M Lib/test/test_dataclasses/__init__.py

diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst
index 954edc4506df1a3..ce59d89843e761d 100644
--- a/Doc/library/dataclasses.rst
+++ b/Doc/library/dataclasses.rst
@@ -100,12 +100,25 @@ Module contents
      ignored.
 
    - *eq*: If true (the default), an :meth:`~object.__eq__` method will be
-     generated.  This method compares the class as if it were a tuple
-     of its fields, in order.  Both instances in the comparison must
-     be of the identical type.
+     generated.
 
-     If the class already defines :meth:`!__eq__`, this parameter is
-     ignored.
+     This method compares the class by comparing each field in order. Both
+     instances in the comparison must be of the identical type.
+
+     If the class already defines :meth:`!__eq__`, this parameter is ignored.
+
+     .. versionchanged:: 3.13
+        The generated ``__eq__`` method now compares each field individually
+        (for example, ``self.a == other.a and self.b == other.b``), rather than
+        comparing tuples of fields as in previous versions.
+
+        This change makes the comparison faster but it may alter results in 
cases
+        where attributes compare equal by identity but not by value (such as
+        ``float('nan')``).
+
+        In Python 3.12 and earlier, the comparison was performed by creating
+        tuples of the fields and comparing them (for example,
+        ``(self.a, self.b) == (other.a, other.b)``).
 
    - *order*: If true (the default is ``False``), :meth:`~object.__lt__`,
      :meth:`~object.__le__`, :meth:`~object.__gt__`, and 
:meth:`~object.__ge__` methods will be
diff --git a/Lib/test/test_dataclasses/__init__.py 
b/Lib/test/test_dataclasses/__init__.py
index 2468e3e64dd621c..423247c92ce3c29 100644
--- a/Lib/test/test_dataclasses/__init__.py
+++ b/Lib/test/test_dataclasses/__init__.py
@@ -2792,6 +2792,55 @@ def __eq__(self, other):
         self.assertEqual(C(1), 5)
         self.assertNotEqual(C(1), 1)
 
+    def test_eq_field_by_field(self):
+        @dataclasses.dataclass
+        class Point:
+            x: int
+            y: int
+
+        p1 = Point(1, 2)
+        p2 = Point(1, 2)
+        p3 = Point(2, 1)
+        self.assertEqual(p1, p2)
+        self.assertNotEqual(p1, p3)
+
+    def test_eq_type_check(self):
+        @dataclasses.dataclass
+        class A:
+            x: int
+
+        @dataclasses.dataclass
+        class B:
+            x: int
+
+        a = A(1)
+        b = B(1)
+        self.assertNotEqual(a, b)
+
+    def test_eq_custom_field(self):
+        class AlwaysEqual(int):
+            def __eq__(self, other):
+                return True
+
+        @dataclasses.dataclass
+        class Foo:
+            x: AlwaysEqual
+            y: int
+
+        f1 = Foo(AlwaysEqual(1), 2)
+        f2 = Foo(AlwaysEqual(2), 2)
+        self.assertEqual(f1, f2)
+
+    def test_eq_nan_field(self):
+        @dataclasses.dataclass
+        class D:
+            x: float
+
+        nan = float('nan')
+        d1 = D(nan)
+        d2 = D(nan)
+        self.assertNotEqual(d1, d2)
+
 
 class TestOrdering(unittest.TestCase):
     def test_functools_total_ordering(self):

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to