Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Python, how can I call copy.deepcopy in my implementation of __deepcopy__()?

I'd like to create a class which can provide a list of attributes which are not deepcopied by copy.deepcopy(). For example like this:

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)

The problem is that I don't think I can call copy.deepcopy() from within __deepcopy__() because that leads to an infinite recursion (since copy.deepcopy() first checks if my object has a __deepcopy__() method). Is there any way I can do this?

like image 548
marius Avatar asked Sep 05 '25 03:09

marius


1 Answers

copy.deepcopy will only call __deepcopy__ if the method exists - we can avoid this by saving the value of __deepcopy__, calling copy.deepcopy(...), and then restoring the value of __deepcopy__ before returning the result:

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
like image 60
l k Avatar answered Sep 07 '25 20:09

l k