The (reference) implementation for copy.deepcopy is here
As you can see, the firsts thing that function does is check for the instance in the memo, so no need to check in your own implementation.
Here is a breakdown of how that function works:
deepcopy(x, memo=None)
checks if
xis in thememo. If it is, return the value associated to it.tries to work out the copying method, by, in that order
- looking for it in the
_deepcopy_dispatchdictionary - checking if
xhas a__deepcopy__method, and using that - checking if it can be reduced (see here). Ie if it can be pickled. If that is the case, it basically runs that, copies the reduced object, and then unpickles it.
- looking for it in the
runs the found method to create a copy
registers that copy in the memo.
(I am ellipsing over some details, read the code if you are interesting in them)
So to answer your questions (and others you may have):
-
- Q: what happens when you override
__deepcopy__ - A: It is called at step 3, instead of the default (unless there was a method in the
_deepcopy_dispatchdictionary, but itthat dictionary should only contain methods for basic types)
- Q: what happens when you override
-
- Q: when does the recursivity happen
- A: It happens when your
__deepcopy__function is called. This one should recursively calldeepcopywith the same memo dictionary
-
- Q: Why does Antony Hatchkins' implementation register the instance in memo if
deepcopyfunction also does it (step 4) - A: because
deepcopyregisters the object inmemoat the very end, whereas to avoid infinite recursion, you need to register it before doing recursive calls
- Q: Why does Antony Hatchkins' implementation register the instance in memo if
Note: For a simpler way to allow your custom classes to be copied, you can also implement the __gestate__ and __setstate__ methods, and relying on the fact that deepcopy falls back on pickling methods