Skip to content

Commit

Permalink
pythongh-103000: Optimise dataclasses asdict/astuple for common types (
Browse files Browse the repository at this point in the history
…python#103005)

Co-authored-by: Carl Meyer <carl@oddbird.net>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
  • Loading branch information
3 people authored and aisk committed Apr 18, 2023
1 parent ef5db87 commit 96fdaa7
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 2 deletions.
31 changes: 29 additions & 2 deletions Lib/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,29 @@ def __repr__(self):
# https://bugs.python.org/issue33453 for details.
_MODULE_IDENTIFIER_RE = re.compile(r'^(?:\s*(\w+)\s*\.)?\s*(\w+)')

# Atomic immutable types which don't require any recursive handling and for which deepcopy
# returns the same object. We can provide a fast-path for these types in asdict and astuple.
_ATOMIC_TYPES = frozenset({
# Common JSON Serializable types
types.NoneType,
bool,
int,
float,
str,
# Other common types
complex,
bytes,
# Other types that are also unaffected by deepcopy
types.EllipsisType,
types.NotImplementedType,
types.CodeType,
types.BuiltinFunctionType,
types.FunctionType,
type,
range,
property,
})

# This function's logic is copied from "recursive_repr" function in
# reprlib module to avoid dependency.
def _recursive_repr(user_function):
Expand Down Expand Up @@ -1291,7 +1314,9 @@ class C:


def _asdict_inner(obj, dict_factory):
if _is_dataclass_instance(obj):
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)
Expand Down Expand Up @@ -1363,7 +1388,9 @@ class C:


def _astuple_inner(obj, tuple_factory):
if _is_dataclass_instance(obj):
if type(obj) in _ATOMIC_TYPES:
return obj
elif _is_dataclass_instance(obj):
result = []
for f in fields(obj):
value = _astuple_inner(getattr(obj, f.name), tuple_factory)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Improve performance of :func:`dataclasses.astuple` and
:func:`dataclasses.asdict` in cases where the contents are common Python types.

0 comments on commit 96fdaa7

Please sign in to comment.