【问题标题】:Best practice to implement copy method in a class?在类中实现复制方法的最佳实践?
【发布时间】:2017-07-12 07:57:11
【问题描述】:

在类中实现copy 方法的最佳做法是什么?

这是我的课的一个例子:

class MyClass:
    def __init__(self, foo, bar=None):
        self.foo = foo
        if bar is not None:
            self.bar = bar
        else:
            self.bar = {'Hello': 'Ciao'}

我发现五年前的一篇帖子建议如下:

import copy

def copy(self):
    return MyClass(copy.copy(self.foo), copy.copy(self.bar))

它仍然是唯一的方法还是有其他可能性?

我需要创建对象的副本以避免函数更改原始对象。函数是这样的:

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)

以下代码的输出是“Ciao”​​、“Ciao”​​,但应该是“Ciao”​​、“Hello”

mc = MyClass('Hello')
translate_and_print(mc)
print(mc.foo)

如果我使用copy() 方法,我会遇到错误:

AttributeError: 'MyClass' 对象没有属性 'copy'

【问题讨论】:

  • 关于你更新的评论,我可以运行myobject = MyClass('foo'),然后运行copy.copy(myobject),没有任何问题。你能提供一段代码来重现你的错误吗?
  • 出于历史原因保留上述评论。看来您的错误是尝试调用my_class.copy(),而您应该调用copy.copy(my_class)
  • 我的帖子已经包含了,特别是最后“你可以直接拨打copy.copy(myobject)”。

标签: python copy


【解决方案1】:

您应该实现__copy__ 方法,可能还应该实现__deepcopy__。文档指出:

为了让一个类定义自己的拷贝实现,它可以定义特殊方法__copy__()__deepcopy__()。前者被调用来实现浅拷贝操作;没有传递额外的参数。后者被调用来实现深拷贝操作;它被传递一个参数,备忘录字典。如果__deepcopy__() 实现需要对组件进行深拷贝,它应该调用deepcopy() 函数,将组件作为第一个参数,将备忘录字典作为第二个参数。

话虽如此,除非你做了一些魔法(例如 C 分配,或调用有状态的 C 库),否则你不需要自己实现 __copy__,但是 python 为你免费提供了这个,你可以简单地调用copy.copy(myobject)

【讨论】:

  • 非常感谢您的建议,但这并没有解释如何实现该方法。
  • 在您的示例中,没有理由实现__copy__。如果您有一个用例,您实际上使用了一些需要您实现它的低级资源,您能否更新您的示例,我们可以提供帮助吗?在您的示例中,您建议的实现没有添加任何内容,因为默认情况下 python 会这样做。
  • 我编辑了这个问题。我的类中没有实现 copy() 方法。
  • 最后的好建议。我在不必要的时候尝试创建复制方法。 copy.copy 是灵丹妙药
【解决方案2】:

你有一个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

【讨论】:

    【解决方案3】:

    Follow 实现只复制,不调用 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-28
      • 2020-09-18
      • 2023-04-09
      • 2017-02-17
      • 1970-01-01
      相关资源
      最近更新 更多