Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice to implement copy method

Tags:

python

copy

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'

like image 490
paolof89 Avatar asked Jul 12 '17 07:07

paolof89


People also ask

What is the use of copy method?

Definition and Usage The copy() method returns a copy of the specified list.

What is the difference between copy copy () and copy Deepcopy ()?

copy() create reference to original object. If you change copied object - you change the original object. . deepcopy() creates new object and does real copying of original object to new one. Changing new deepcopied object doesn't affect original object.

What is deep copy vs shallow copy?

Shallow Copy stores the copy of the original object and points the references to the objects. Deep copy stores the copy of the original object and recursively copies the objects as well. Shallow copy is faster. Deep copy is comparatively slower.

What is difference between deep copy and shallow copy in Python?

A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original. A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.


3 Answers

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)

like image 123
Jonas Adler Avatar answered Oct 01 '22 16:10

Jonas Adler


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

like image 36
Arun V Jose Avatar answered Oct 01 '22 17:10

Arun V Jose


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
like image 30
RedEyed Avatar answered Oct 01 '22 18:10

RedEyed