【问题标题】:copy vs deepcopy: semantics复制与深度复制:语义
【发布时间】:2012-05-02 11:44:28
【问题描述】:

我的班级代表各种系统的状态。每个实例有两个属性:一个是同一系统所有状态之间共享的容器,另一个是每个实例唯一的容器。

状态的副本应重用“共享”属性,但创建“唯一”属性的深层副本。这确实是唯一有意义的复制语义(状态的副本自然是同一系统的状态)。

我想为阅读和维护我的代码的人创造最小的惊喜。为了我的目的,我应该覆盖 __deepcopy____copy__ 吗?

【问题讨论】:

  • __deepcopy__ 如果您要进行投票...
  • 嗯,我希望能达成共识 :) 在每个人都有机会看到每个人的回应之后,它可能仍然是。

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


【解决方案1】:

真的有必要使用copy模块来复制这个类的实例吗?我认为,与其重写 __copy____deepcopy__,不如为您的类创建一个 copy 方法,该方法使用您定义的复制语义返回一个新对象。

如果出于某种一致性原因您确实需要使用复制模块,那么我认为__deepcopy__ 更合适。如果所有实例共享一个容器是类的定义行为,那么可以合理地假设__deepcopy__ 的实现会尊重这一点。

【讨论】:

  • 我可以不用copy 模块。但是如果我定义一个copy 方法,读者不会认为它是一个浅拷贝,就像dictset 一样?
  • @max,你的类是dictset 的子类吗?如果不是,那么读者不应假定您的类的 copy 方法应该从内置类型中模仿 copy
  • @max:我认为你总是会让一些读者感到惊讶,因为你想要的语义既不是完全浅的也不是完全深的。但在定义自定义复制语义的所有可能位置中,我认为类的copy 方法是最有可能被自定义的方法。如果完全浅层和完全深层语义对您的类确实没有意义,那么为什么不同时覆盖它们呢? (您可以让__copy____deepcopy__ 调用班级的copy。)
  • @F.J:所以,我对state.copy 方法感觉很舒服。我可能应该让 deepcopy 仍然被覆盖,否则做copy.deepcopy({state1, state2}) 的人最终会不必要地复制“shared”属性。
  • @John Y:我可能会让__copy__ 引发异常,因为调用它真的没有意义。
【解决方案2】:

这和你的情况相似吗?

import copy

class Foo(object):
    shared = [[]]
    def __init__(self):
        self.perinstance = [[]]

如果是这样,那么您似乎不需要定义__copy____deepcopy__,因为copy.deepcopy 的默认行为共享类属性和deepcopies 实例属性:

x = Foo()
z = copy.deepcopy(x)
assert id(z.shared) == id(x.shared)
assert id(z.shared[0]) == id(x.shared[0])
assert id(z.perinstance) != id(x.perinstance)
assert id(z.perinstance[0]) != id(x.perinstance[0])

【讨论】:

  • 不幸的是,我的共享属性是一个实例属性。我的解释不准确。 “shared”属性可以在实例之间有所不同,但前提是它们对应于不同的系统。复制语义(如您所料)从同一系统创建状态的副本,因此它具有相同的共享属性值。我正在更新问题以澄清这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-03
  • 2011-09-11
  • 2020-11-08
  • 1970-01-01
  • 2017-04-09
相关资源
最近更新 更多