diff --git a/Lib/copy.py b/Lib/copy.py index 6149301ad1389e2..f7fd680657b85a5 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -122,9 +122,8 @@ def deepcopy(x, memo=None): if memo is None: memo = {} else: - y = memo.get(d, None) - if y is not None: - return y + if d in memo: + return memo[d] copier = _deepcopy_dispatch.get(cls) if copier is not None: diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py index 9455c9e00514ca4..0e7ed8fe48f9df0 100644 --- a/Lib/test/test_copy.py +++ b/Lib/test/test_copy.py @@ -939,6 +939,17 @@ def m(self): self.assertIs(g.b.__self__, g) g.b() + def test_deepcopy_memo_none_result(self): + # Objects whose deepcopy result is None must still be memoized. + class C: + call_count = 0 + def __deepcopy__(self, memo): + C.call_count += 1 + return None + obj = C() + copy.deepcopy([obj, obj, obj]) + self.assertEqual(C.call_count, 1) + class TestReplace(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2026-07-24-00-02-00.gh-issue-154594.Xk7mQ2.rst b/Misc/NEWS.d/next/Library/2026-07-24-00-02-00.gh-issue-154594.Xk7mQ2.rst new file mode 100644 index 000000000000000..5f96bba97aa19f4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-24-00-02-00.gh-issue-154594.Xk7mQ2.rst @@ -0,0 +1,2 @@ +Fix :func:`copy.deepcopy` so that an object whose deep copy is ``None`` is +still memoized. Patch by tonghuaroot.