2

In "How to override the copy/deepcopy operations for a Python object?" post, it is written in one of the answers that:

 def __deepcopy__(self, memo): cls = self.__class__ result = cls.__new__(cls) memo[id(self)] = result for k, v in self.__dict__.items(): setattr(result, k, deepcopy(v, memo)) return result 

Is a possible way of overriding the deepcopy method. I do not understand what each of the lines does. What is the purpose of this implementation? Can't I just create my own copy method with something specific for my class like the following?

def my_copy(self, original_obj): obj = MyClass() obj.a = (copy of a from the other object) obj.b = (copy of b from the other object) ... return obj 
1
  • 1
    Purpose: Sometimes your class contains attributes that can either not be deep-copied or that you do not want to copy but instead share the existing object (e.g. weak references, DB connections, ...). In the for loop in the example, you could filter such attributes and handle them as you need. Commented Jul 24, 2019 at 11:33

1 Answer 1

3

You are right you could to this in the way you presented. However this would be specific to your object implementation. The example you posted is much more generic and could handle copying many different classes of objects. It could also be made as a mixin to easy add it to your class.

The code presented, do this by:

def __deepcopy__(self, memo): cls = self.__class__ # Extract the class of the object result = cls.__new__(cls) # Create a new instance of the object based on extracted class memo[id(self)] = result for k, v in self.__dict__.items(): setattr(result, k, deepcopy(v, memo)) # Copy over attributes by copying directly or in case of complex objects like lists for exaample calling the `__deepcopy()__` method defined by them. Thus recursively copying the whole tree of objects. return result 

Note also that if your class consisted of complex attributes like lists you would also need to call directly deepcopy on them or otherwise you would end up with a shallow copy for some of the attributes.

EDIT

memo is a dict, where id-to-object correspondence is kept to reconstruct complex object graphs perfectly.

Sign up to request clarification or add additional context in comments.

8 Comments

also note that if your class isn't using __dict__ to store its attributes (e.g. it's using __slots__) then this implementation won't do the right thing
Thanks, I've 2 questions. First, why the first 2 lines instead of doing result = ClassName(...)? Aren't both creating a new object? Also, what is the "memo" and what is that line needed for?
@SamMason where is it defined what the class is using to store its attributes?
@Miguel classes use __dict__ by default. if you wrote the class yourself you'll know what it's using (i.e. probably the default) and if you didn't then try searching for __slots__ in the definition. maybe also check out stackoverflow.com/q/472000/1358308
@Miguel Yes it is overwritten for that one class. However if you create a base class with a generic deepcopy like example you posted you will not have to redefine it in all child classes. If you use the class name explicitly inheritance will break your code.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.