]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-103000: Optimise `dataclasses.asdict` for the common case (#104364)
authorAlex Waygood <Alex.Waygood@Gmail.com>
Wed, 10 May 2023 21:43:51 +0000 (22:43 +0100)
committerGitHub <noreply@github.com>
Wed, 10 May 2023 21:43:51 +0000 (22:43 +0100)
Co-authored-by: David Ellis <ducksual@gmail.com>
Lib/dataclasses.py
Misc/NEWS.d/next/Library/2023-05-10-19-33-36.gh-issue-103000.j0KSfD.rst [new file with mode: 0644]

index b0b8a773b7594f5852b9d3077aa5c58b016936d5..3eacba840db426c5d68027adf883d230c1228393 100644 (file)
@@ -1324,11 +1324,18 @@ def _asdict_inner(obj, dict_factory):
     if type(obj) in _ATOMIC_TYPES:
         return obj
     elif _is_dataclass_instance(obj):
-        result = []
-        for f in fields(obj):
-            value = _asdict_inner(getattr(obj, f.name), dict_factory)
-            result.append((f.name, value))
-        return dict_factory(result)
+        # fast path for the common case
+        if dict_factory is dict:
+            return {
+                f.name: _asdict_inner(getattr(obj, f.name), dict)
+                for f in fields(obj)
+            }
+        else:
+            result = []
+            for f in fields(obj):
+                value = _asdict_inner(getattr(obj, f.name), dict_factory)
+                result.append((f.name, value))
+            return dict_factory(result)
     elif isinstance(obj, tuple) and hasattr(obj, '_fields'):
         # obj is a namedtuple.  Recurse into it, but the returned
         # object is another namedtuple of the same type.  This is
diff --git a/Misc/NEWS.d/next/Library/2023-05-10-19-33-36.gh-issue-103000.j0KSfD.rst b/Misc/NEWS.d/next/Library/2023-05-10-19-33-36.gh-issue-103000.j0KSfD.rst
new file mode 100644 (file)
index 0000000..f84ec5c
--- /dev/null
@@ -0,0 +1,2 @@
+Improve performance of :func:`dataclasses.asdict` for the common case where
+*dict_factory* is ``dict``. Patch by David C Ellis.