Skip to content

Commit d034590

Browse files
DavidCElliscarljmAlexWaygood
authored
gh-103000: Optimise dataclasses asdict/astuple for common types (#103005)
Co-authored-by: Carl Meyer <[email protected]> Co-authored-by: Alex Waygood <[email protected]>
1 parent f80014a commit d034590

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

Lib/dataclasses.py

+29-2
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,29 @@ def __repr__(self):
222222
# https://bugs.python.org/issue33453 for details.
223223
_MODULE_IDENTIFIER_RE = re.compile(r'^(?:\s*(\w+)\s*\.)?\s*(\w+)')
224224

225+
# Atomic immutable types which don't require any recursive handling and for which deepcopy
226+
# returns the same object. We can provide a fast-path for these types in asdict and astuple.
227+
_ATOMIC_TYPES = frozenset({
228+
# Common JSON Serializable types
229+
types.NoneType,
230+
bool,
231+
int,
232+
float,
233+
str,
234+
# Other common types
235+
complex,
236+
bytes,
237+
# Other types that are also unaffected by deepcopy
238+
types.EllipsisType,
239+
types.NotImplementedType,
240+
types.CodeType,
241+
types.BuiltinFunctionType,
242+
types.FunctionType,
243+
type,
244+
range,
245+
property,
246+
})
247+
225248
# This function's logic is copied from "recursive_repr" function in
226249
# reprlib module to avoid dependency.
227250
def _recursive_repr(user_function):
@@ -1291,7 +1314,9 @@ class C:
12911314

12921315

12931316
def _asdict_inner(obj, dict_factory):
1294-
if _is_dataclass_instance(obj):
1317+
if type(obj) in _ATOMIC_TYPES:
1318+
return obj
1319+
elif _is_dataclass_instance(obj):
12951320
result = []
12961321
for f in fields(obj):
12971322
value = _asdict_inner(getattr(obj, f.name), dict_factory)
@@ -1363,7 +1388,9 @@ class C:
13631388

13641389

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

0 commit comments

Comments
 (0)