【发布时间】:2018-05-28 11:31:54
【问题描述】:
如何实现基类的复制,该复制适用于继承的新属性而没有为继承的类实现__copy__(意味着新属性的哑副本)?
即我们有一个包含一个用户定义和一个计算(或外部参考,不应复制)字段的类。所以副本应该创建实例,仅基于用户定义的字段:
class A(object):
def __init__(self, a):
self.a = a
self.b = a+1
def __copy__(self):
return A(self.a)
此时copy 工作正常。
然后我们引入继承类,它的构造函数根据它自己的args计算基构造函数的args,并且还引入了新字段,所以继承构造函数的签名是完全不同的并且对于基类是未知的(共同的):
class B(A):
def __init__(self, c):
A.__init__(self, c+100)
self.c=c
此时copy 显然工作不正常,返回A 实例。当然,我们可以为继承的类实现自己的__copy__,但是当我们引入一些属性时,这非常不方便,应该以普通方式复制。所以我想要实现的是,通过A.__copy__ 复制继承类B 的“A 部分”,但仍保留标准副本,无需为所有继承类重新实现__copy__。那么对于这种情况是否有任何“设计模式”?
更新:
我想将示例从copy 重新表述为deepcopy,这更接近实际情况。所以这个想法是一样的——我们必须管理 A 类的深度复制,它包含不应该被深度复制的引用(即链接到容器,其中包含对象)。但我们不想管理继承类的深度复制。
from copy import deepcopy
class A:
def __init__(self, content, container):
self.content = content
self.container = container
def __deepcopy__(self, memo):
return A(deepcopy(self.content, memo), self.container)
class B(A):
def __init__(self, attr):
A.__init__(self, [1,2,3], self)
self.attr = attr
b = B(123)
b1=deepcopy(b) # wrong!
看起来我找到了适合我的特定情况的模式(谢谢@mhawke):首先复制所有内容,然后只深度复制必要的字段。
class A:
def __deepcopy__(self, memo):
o = copy(self)
o.content = deepcopy(self.content)
return o
但它不能解决常见情况下的问题:对于 deepcopy,我想对继承的属性进行 deepcopy,而不是复制它,并且仅在必要时管理 deepcoping 以进行覆盖。
【问题讨论】:
-
copy.copy()有什么问题?它将继承类的对象复制到同一类的实例中。 -
我想在这种特殊情况下没有错。也许更好地考虑 deepcopy,在很多情况下应该覆盖基类 deepcopy 以排除处理某些链接,即链接到某些列表中的相邻对象。问题是如何实现基类副本,这对于典型的重写工作正常。