https://github.com/python/cpython/commit/5539c2a5437acc4f4719aabac375368e0d310bd9
commit: 5539c2a5437acc4f4719aabac375368e0d310bd9
branch: main
author: tonghuaroot (童话) <[email protected]>
committer: eendebakpt <[email protected]>
date: 2026-09-17T21:11:17+02:00
summary:

gh-154594: Fix deepcopy memo lookup when __deepcopy__ returns None (#154595)

* gh-154594: Fix deepcopy memo lookup when __deepcopy__ returns None

* Use 'd in memo' lookup instead of a sentinel

Addresses review: clearer, no sentinel, and the test treats memo as opaque.

* Apply review suggestions: shorten NEWS, use class attribute in test

---------

Co-authored-by: Pieter Eendebak <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-07-24-00-02-00.gh-issue-154594.Xk7mQ2.rst
M Lib/copy.py
M Lib/test/test_copy.py

diff --git a/Lib/copy.py b/Lib/copy.py
index 6149301ad1389e..f7fd680657b85a 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 13b7ce29565dee..2a12a6737df163 100644
--- a/Lib/test/test_copy.py
+++ b/Lib/test/test_copy.py
@@ -951,6 +951,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 00000000000000..5f96bba97aa19f
--- /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.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to