Best practice to implement copy method

时间:2017-07-12 07:57:12

标签: python

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 个答案:

答案 0 :(得分:6)

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)

答案 1 :(得分:3)

您有一个AttributeError,我认为这是因为您只是创建了一个copy方法,而不是您需要创建__copy__方法。

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__浅层复制方法和__deepcopy__深层复制方法。

我希望你明白这一点,Here is the link i follow

答案 2 :(得分:1)

以下实现仅复制而无需调用init()方法。

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