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'
You 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
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 the deepcopy()
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)
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