[Python-checkins] Small speedup for dataclass __eq__ and __repr__ (#104904)

ericvsmith webhook-mailer at python.org
Tue May 30 12:35:38 EDT 2023


https://github.com/python/cpython/commit/18cfc1eea569f0ce72ad403840c0e6cc5f81e1c2
commit: 18cfc1eea569f0ce72ad403840c0e6cc5f81e1c2
branch: main
author: Raymond Hettinger <rhettinger at users.noreply.github.com>
committer: ericvsmith <ericvsmith at users.noreply.github.com>
date: 2023-05-30T12:35:30-04:00
summary:

Small speedup for dataclass __eq__ and __repr__ (#104904)

Faster __repr__ with str.__add__ moved inside the f-string. For __eq__ comp;are field by field instead of building temporary tuples.

Co-authored-by: Shantanu <12621235+hauntsaninja at users.noreply.github.com>

files:
M Lib/dataclasses.py

diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py
index 3eacba840db4..e766a7b554af 100644
--- a/Lib/dataclasses.py
+++ b/Lib/dataclasses.py
@@ -627,7 +627,7 @@ def _init_fn(fields, std_fields, kw_only_fields, frozen, has_post_init,
 def _repr_fn(fields, globals):
     fn = _create_fn('__repr__',
                     ('self',),
-                    ['return self.__class__.__qualname__ + f"(' +
+                    ['return f"{self.__class__.__qualname__}(' +
                      ', '.join([f"{f.name}={{self.{f.name}!r}}"
                                 for f in fields]) +
                      ')"'],
@@ -1085,13 +1085,17 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen,
     if eq:
         # Create __eq__ method.  There's no need for a __ne__ method,
         # since python will call __eq__ and negate it.
-        flds = [f for f in field_list if f.compare]
-        self_tuple = _tuple_str('self', flds)
-        other_tuple = _tuple_str('other', flds)
-        _set_new_attribute(cls, '__eq__',
-                           _cmp_fn('__eq__', '==',
-                                   self_tuple, other_tuple,
-                                   globals=globals))
+        cmp_fields = (field for field in field_list if field.compare)
+        terms = [f'self.{field.name}==other.{field.name}' for field in cmp_fields]
+        field_comparisons = ' and '.join(terms) or 'True'
+        body =  [f'if other.__class__ is self.__class__:',
+                 f' return {field_comparisons}',
+                 f'return NotImplemented']
+        func = _create_fn('__eq__',
+                          ('self', 'other'),
+                          body,
+                          globals=globals)
+        _set_new_attribute(cls, '__eq__', func)
 
     if order:
         # Create and set the ordering methods.



More information about the Python-checkins mailing list