What is the best practice to implement the copy method in a class?
Here is an example of my class:
class MyClass:
def __init__(self, foo, bar=None):
self.foo = foo
if bar is not None:
self.bar = bar
else:
self.bar = {'Hello': 'Ciao'}
I found a post of five years ago that suggests the following way:
import copy
def copy(self):
return MyClass(copy.copy(self.foo), copy.copy(self.bar))
Is it still the only way to do it or are there other possibilities?
I need to create a copy of my object to avoid that a function changes the original object. The function is something like this:
def translate_and_print(my_class, dict={'Hello':'Ciao'}):
temp = my_class # here I want to use the copy method: temp = my_class.copy()
temp.foo = temp.bar[temp.foo]
print(temp.foo)
The output of the following code is "Ciao", "Ciao" but should be "Ciao", "Hello"
mc = MyClass('Hello')
translate_and_print(mc)
print(mc.foo)
If I use the copy() method I have the error:
AttributeError: 'MyClass' object has no attribute 'copy'
3 Answers 3
You should implement the __copy__ method, and possibly also __deepcopy__. The documentation states:
In order for a class to define its own copy implementation, it can define special methods
__copy__()and__deepcopy__(). The former is called to implement the shallow copy operation; no additional arguments are passed. The latter is called to implement the deep copy operation; it is passed one argument, the memo dictionary. If the__deepcopy__()implementation needs to make a deep copy of a component, it should call thedeepcopy()function with the component as first argument and the memo dictionary as second argument.
With that said, unless you do some magic (e.g. C allocations, or calls to statefull C libraries), you should not need to implement __copy__ yourself, but python provides this for you for free, and you can simply call copy.copy(myobject)
4 Comments
__copy__. If you have a use case where you actually use some low-level resources that require you to implement it, could you update your example and we can help out with that? In your example, the implementation you suggest adds nothing since python does that by default.copy.copy was magic bulletYou got an AttributeError, I think that's because you just create a copy method, instead of that you need to create __copy__ method.
import copy
class MyClass:
def __init__(self, name):
self.name = name
def __copy__(self):
return MyClass(self.name)
def __deepcopy__(self, memo):
return MyClass(copy.deepcopy(self.name, memo))
__copy__ method for shallow copy and __deepcopy__ for deep copy.
I hope you got the point, Here is the link i follow
2 Comments
MyClass initialiser. For example, copy of child class instance would become an instance of MyClass.import copy! On the other hand just def copy(self) instead of def __copy__(self) has no such requirement.Follow implementation makes just copy, without calling the init() method.
class MyClass(BaseClass):
def __init__(self, name):
super().__init__()
self.name = name
def __copy__(self):
obj = type(self).__new__(self.__class__)
obj.__dict__.update(self.__dict__)
return obj
myobject = MyClass('foo'), and then docopy.copy(myobject)without any issues. Can you provide a piece of code that reproduces your error?my_class.copy(), whereas you should be callingcopy.copy(my_class).copy.copy(myobject)" in the end.