deepcopy problem with new-style classes in Python 2.3a2
Stephen C Phillips
news at scphillips.com
Wed Mar 12 15:59:45 EST 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