Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Supporting the deep copy operation on a custom class?

Tags:

python

copy

I have a dict subclass that adds new methods and features, The main thing that I wanted to support is recursive update which works by updating every nested dict one by one unlike the dict.update method.

I'm using the copy.deepcopy function just like any other object, the problem is that it's not working when I added attribute access to this class:

__getattr__ = dict.__getitem__
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__

Now I get this error:

KeyError: '__deepcopy__'

The copy.deepcopy function is trying to use a __deepcopy__ method on this object:

copier = getattr(x, "__deepcopy__", None)

Why after adding the __getattr__ this happened ? is there a way to fix it without implementing a __deepcopy__ method ?


I never used the __deepcopy__ method so I tried adding one, and this is what I have:

def __deepcopy__(self, memo):
    # create a new instance of this object
    new_object = type(self)()

    # iterate over the items of this object and copy each one
    for key, value in self.iteritems():
        new_object[key] = copy.deepcopy(value, memo)

    return new_object

Is this the right way to implement __deepcopy__ ?

like image 276
Pierre Avatar asked Sep 22 '14 15:09

Pierre


1 Answers

You don't need to implement __deepcopy__ here.

The problem is that your __getattr__ always calls __getitem__, which will raise a KeyError for a nonexistent attribute. But __getattr__ is expected to raise an AttributeError in this case.

The implementation of getattr catches the AttributeError, but not the KeyError, and therefore the exception is unhandled.

You should change __getattr__ to correctly raise AttributeError in this case.

like image 95
interjay Avatar answered Sep 24 '22 06:09

interjay