deepcopy problem with new-style classes in Python 2.3a2

Stephen C Phillips news at scphillips.com
Wed Mar 12 21:59:45 CET 2003


Alex Martelli wrote:
> Stephen C Phillips wrote:
> 
> 
>>Hi,
>>I am having a problem using deepcopy on a complex data structure.  I
>>think it can be distilled down to a basic difficulty shown below (thanks
>>to Jp Calderone).
>>With Python 2.3a2 (or Python 2.2.2) I get this:
>>
>>
>>>>>class Foo(object):
>>>>
>>...     pass
>>...
>>
>>>>>f = Foo()
>>>>>f.foo = f
>>>>>g = copy.deepcopy(f)
>>>>>g is not f
>>>>
>>True
>>
>>>>>f is f.foo
>>>>
>>True
>>
>>>>>g is g.foo
>>>>
>>False
>>
>>Obviously I would like "g.foo is foo" to be True.
>>g.foo is not f either, it is some other empty object.
>>With old-style classes I get the desired behaviour.  Can anyone explain
>>what the problem is?
> 
> 
> Module copy is currently not able to install a "proper" deep-copier function
> that works automatically and correctly for instances of new-style classes,
> in good part because it has no way to identify "instances of new-style
> classes" as such (as opposed to, e.g., instances of subclasses of list, or
> dict, etc -- they're all much the same thing, but need very different
> approaches to deep-copying).
> 
> I suggest you submit this as a bug, and if you need a workaround you can
> ensure your new-style classes contain a __deepcopy__ that satisfies your
> needs, such as:
> 
>     def __deepcopy__(self, memo):
>         x = Foo.__new__(Foo)
>         memo[id(self)] = x
>         for n, v in self.__dict__.iteritems():
>             setattr(x, n, copy.deepcopy(v, memo))
>         return x
> 
> for new-style classes whose instances hold all of their state in __dict__,
> and so on.

Thank you.  I thought it might be a bug, but I am not any where near 
expert enough to know.

My problem is not as simple as that described above, so I think that 
your work-around will not be sufficient.
I have a class with several sub-classes (and sub-classes of those). 
Some of these classes may use __getstate__ and __setstate__ to remove 
some attributes from the copying process (and I would like the 
__getstate__ of the subclass to be in addition to the behaviour of its 
parent's __getstate__).  I think I can see how to begin modifying your 
work-around to cope with this (but cannot try code out from this computer!).

Would something like this be a good start?

def __deepcopy__(self, memo):
     x = self.__class__.__new__(self.__class__)
     memo[id(self)] = x
     dict = {}
     for n, v in self.__getstate__.iteritems():
         dict[n] = copy.deepcopy(v, memo)
     x.__setstate__(dict)
     return x


Thanks again.

Stephen.





More information about the Python-list mailing list