【问题标题】:deepcopy override clarificationdeepcopy 覆盖说明
【发布时间】:2019-07-24 11:26:21
【问题描述】:

"How to override the copy/deepcopy operations for a Python object?" 的帖子中,写在以下答案之一中:

    def __deepcopy__(self, memo):
    cls = self.__class__
    result = cls.__new__(cls)
    memo[id(self)] = result
    for k, v in self.__dict__.items():
        setattr(result, k, deepcopy(v, memo))
    return result

是覆盖 deepcopy 方法的一种可能方式。我不明白每一行的作用。这个实施的目的是什么?我不能只使用以下特定于我的班级的东西来创建自己的复制方法吗?

def my_copy(self, original_obj):
    obj = MyClass()
    obj.a = (copy of a from the other object)
    obj.b = (copy of b from the other object)
    ...
    return obj

【问题讨论】:

  • 目的:有时你的类包含不能被深度复制或者你不想复制而是共享现有对象的属性(例如弱引用,数据库连接,......)。在示例中的for 循环中,您可以过滤这些属性并根据需要进行处理。

标签: python python-3.x class deep-copy


【解决方案1】:

你是对的,你可以按照你提出的方式做到这一点。但是,这将特定于您的对象实现。您发布的示例更加通用,可以处理复制许多不同类别的对象。它也可以作为一个 mixin 来轻松添加到你的类中。

提供的代码,通过以下方式执行:

def __deepcopy__(self, memo):
        cls = self.__class__ # Extract the class of the object
        result = cls.__new__(cls) # Create a new instance of the object based on extracted class
        memo[id(self)] = result
        for k, v in self.__dict__.items():
            setattr(result, k, deepcopy(v, memo)) # Copy over attributes by copying directly or in case of complex objects like lists for exaample calling the `__deepcopy()__` method defined by them. Thus recursively copying the whole tree of objects.
        return result

另请注意,如果您的类包含复杂的属性(如列表),您还需要直接对它们调用 deepcopy,否则您最终会得到一些属性的浅拷贝。

编辑

memo 是一个字典,其中保留了 id 到对象的对应关系,以完美地重构复杂的对象图。

【讨论】:

  • 还要注意,如果你的类没有使用__dict__ 来存储它的属性(例如它使用__slots__)那么这个实现不会做正确的事情
  • 谢谢,我有 2 个问题。首先,为什么前 2 行而不是 result = ClassName(...)?不是都在创建一个新对象吗?另外,什么是“备忘录”,该行需要什么?
  • @SamMason 它在哪里定义了类用于存储其属性的内容?
  • @Miguel 类默认使用__dict__。如果你自己编写了这个类,你就会知道它在使用什么(即可能是默认值),如果你没有,那么尝试在定义中搜索__slots__。也许还可以查看stackoverflow.com/q/472000/1358308
  • @Miguel 是的,它被该类覆盖。但是,如果您使用您发布的示例创建具有通用 deepcopy 的基类,则不必在所有子类中重新定义它。如果你显式地使用类名,继承会破坏你的代码。
猜你喜欢
  • 2021-08-05
  • 1970-01-01
  • 2017-12-28
  • 1970-01-01
  • 1970-01-01
  • 2021-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多