2

我想创建一个类,它可以提供一个未被深拷贝的属性列表copy.deepcopy()。例如像这样:

class CustomDeepcopy(object):

    a = SomeSimpleObject()
    b = SomeBigObject()

    def dont_deepcopy(self):
        return ['b']

    def __deepcopy__(self,memo):
        #Somehow call copy.deepcopy(self) and have it  
        #deepcopy self.a but not self.b
        #
        #For example, this *almost* works, 
        for attr in self.dont_deepcopy():
            val = getattr(self,attr,None)
            if val is not None:
                 memo[id(val)]=val
        return copy.deepcopy(self,memo)

问题是我认为我不能copy.deepcopy()从内部调用,__deepcopy__()因为这会导致无限递归(因为copy.deepcopy()首先检查我的对象是否有__deepcopy__()方法)。有什么办法可以做到这一点吗?

4

2 回答 2

1

任何时候你实现一个特殊的方法(比如__getattr__, __deepcopy__, __str__, 等等)你要么需要用 super 去提升 mro 要么使用原始的一些子集。

我不完全清楚你是如何记忆属性的,但我会简化你的例子。假设您总是使用相同的 a(并且它是不可变的,不需要复制),但除此之外,您想复制 b。(并且您可以将ab直接传递给构造函数以创建一个新对象。

class CustomDeepcopy(object):
    def __init__(self, a=None, b=None):
        if a:
            self.a = a
        if b:
            self.b = b

    a = SomeSimpleObject()
    b = SomeBigObject()

    @property
    def dont_deepcopy(self):
        return ['b']
    @property
    def deepcopy_attributes(self):
        return ['a']

    def __deepcopy__(self,memo):
        new_kwargs = dict((k, getattr(self, attr, None)) for attr in self.dont_deepcopy)
        for attr in self.deepcopy_attributes:
            new_kwargs[attr] = copy.deepcopy(getattr(self, attr, None))
        return self.__class__(**new_kwargs)
于 2013-06-24T04:22:26.380 回答
1

copy.deepcopy只有在方法存在时才会调用__deepcopy__- 我们可以通过保存 的值__deepcopy__、调用copy.deepcopy(...)、然后__deepcopy__在返回结果之前恢复 的值来避免这种情况:

class CustomDeepcopy(object):

    a = SomeSimpleObject()
    b = SomeBigObject()

    def dont_deepcopy(self):
        return ['b']

    def __deepcopy__(self,memo):
        for attr in self.dont_deepcopy():
            val = getattr(self,attr,None)
            if val is not None:
                 memo[id(val)]=val
        deepcopy_method = self.__deepcopy__
        self.__deepcopy__ = None
        result = copy.deepcopy(self,memo)
        self.__deepcopy__ = deepcopy_method
        return result
于 2017-06-22T14:34:08.317 回答