Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Optimize deepcopy of empty containers
  • Loading branch information
lgeiger committed Jun 30, 2024
commit f317c1b3979d1382201f369c476993b517ef2b1e
14 changes: 10 additions & 4 deletions Lib/copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,19 +123,23 @@ def deepcopy(x, memo=None, _nil=[]):

cls = type(x)

if cls in _atomic_types:
if cls in _atomic_types or (cls in _immutable_iterables and len(x) == 0):
return x

d = id(x)
if memo is None:
if cls in _mutable_iterables and len(x) == 0:
return cls()
d = id(x)
memo = {}
else:
d = id(x)
y = memo.get(d, _nil)
if y is not _nil:
return y

copier = _deepcopy_dispatch.get(cls)
if copier is not None:
if cls in _mutable_iterables and len(x) == 0:
y = cls()
elif copier := _deepcopy_dispatch.get(cls):
y = copier(x, memo)
else:
if issubclass(cls, type):
Expand Down Expand Up @@ -173,6 +177,8 @@ def deepcopy(x, memo=None, _nil=[]):
_atomic_types = {types.NoneType, types.EllipsisType, types.NotImplementedType,
int, float, bool, complex, bytes, str, types.CodeType, type, range,
types.BuiltinFunctionType, types.FunctionType, weakref.ref, property}
_mutable_iterables = {list, dict, set}
_immutable_iterables = {tuple, frozenset}

_deepcopy_dispatch = d = {}

Expand Down