Python 复制与深度复制:语义

Python 复制与深度复制:语义,python,python-3.x,copy,deep-copy,Python,Python 3.x,Copy,Deep Copy,我的类代表各种系统的状态。每个实例都有两个属性:一个是在同一系统的所有状态之间共享的容器,另一个是每个实例唯一的容器 状态的副本应该重用“共享”属性,但创建“唯一”属性的深度副本。这实际上是唯一有意义的复制语义(很自然,状态的副本是同一系统的状态) 我想为阅读和维护我的代码的人创造最少的惊喜。为了我的目的,我应该重写\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

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

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


我想为阅读和维护我的代码的人创造最少的惊喜。为了我的目的,我应该重写
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?我认为应该为类创建一个
copy
方法,使用定义的复制语义返回一个新对象,而不是重写
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
\uuuuuuuuuuuuuuuuuu deepcopy


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

这与您的情况类似吗

import copy

class Foo(object):
    shared = [[]]
    def __init__(self):
        self.perinstance = [[]]
如果是这样,则似乎不需要定义
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
\uuuuuuuuuuuuuuuuuuuuuuuu

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])

\uuuu deepcopy\uuuuu
如果你正在进行民意调查……我希望能有一个一致的观点:)而且在每个人都有机会看到每个人的反应之后,它可能仍然是。我不介意使用
复制
模块。但是如果我定义了一个
copy
方法,读者难道不会认为它是一个浅拷贝,就像
dict
set
一样吗?@max,你的类是
dict
set
的子类吗?如果不是,那么读者就不应该认为类的
copy
方法应该模仿内置类型的
copy
。@max:我想你总是会让一些读者感到惊讶,因为你想要的语义既不是很浅也不是很深。但是在所有可能定义定制复制语义的地方,我认为类的
copy
方法是最有可能被定制的方法。如果完全浅层和完全深层的语义对您的类来说真的没有意义,那么为什么不重写它们呢?(你可以让
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。我可能应该让deepcopy仍然被覆盖,因为如果不这样做,执行
copy.deepcopy({state1,state2})
操作的人会不必要地复制“shared”属性。@John Y:我可能会让
\ucopy\uuuuuuuu
引发异常,因为调用它毫无意义。不幸的是,我的共享属性是实例属性。我的解释不准确。“共享”属性可以在实例之间变化,但前提是它们对应于不同的系统。复制语义(正如您所期望的)从同一系统创建状态的副本,因此它具有相同的共享属性值。我正在更新问题以澄清这一点。