Challenge supporting custom deepcopy with inheritance
Gabriel Genellina
gagsl-py2 at yahoo.com.ar
Tue Jun 2 00:51:35 EDT 2009
En Mon, 01 Jun 2009 14:19:19 -0300, Michael H. Goldwasser
<goldwamh at slu.edu> escribió:
> I can examine the inherited slots to see which special methods are
> there, and to implement my own __deepcopy__ accordingly. But to do
> so well seems to essentially require reimplementing the complicated
> logic of the copy.deepcopy function. That is, if my new class is
> the first to be implementing an explicit __deepcopy__ function, I
> seem to have no easy way to invoke the inherited version of
> "deepcopy(self)".
Yes, that's a problem. But there is a workaround: since __deepcopy__ is
searched *in the instance* (unlike many other __special__ methods, that
are usually searched in the class itself) you can fool the copy logic into
thinking there is no __deepcopy__ method defined, just by (temporarily)
setting an instance attribute __deepcopy__ to None. (It's a hack, anyway)
<code>
import copy
class A(object):
def __init__(self, x, y):
self.x = x
self.y = y
# these two methods implement copy and pickle behaviour
# we can't change them
def __reduce__(self):
return (self.__newobj__, (), self.__dict__)
@classmethod
def __newobj__(cls, *args):
return cls.__new__(cls, *args)
class B(A):
def __init__(self, x, y, filename):
A.__init__(self, x, y)
self.file = open(filename, "at")
def __deepcopy__(self, memo):
# Problem: how to call the inherited __deepcopy__ implementation
# when there is none?
# The logic is inside the copy.deepcopy function, not in
# object.__deepcopy__
# hack: make deepcopy() think this method doesn't exist
self.__deepcopy__ = None
try:
dup = copy.deepcopy(self, memo)
del dup.__deepcopy__
finally:
del self.__deepcopy__
# now, do the special stuff
dup.file = open(self.file.name, "at")
return dup
obj = B(1, 2, "testfile")
print "obj", obj, vars(obj)
dup = copy.deepcopy(obj)
print "obj", obj, vars(obj)
print "dup", dup, vars(dup)
</code>
obj <__main__.B object at 0x00BEC0F0> {'y': 2, 'x': 1, 'file': <
open file 'testfile', mode 'at' at 0x00B46C00>}
obj <__main__.B object at 0x00BEC0F0> {'y': 2, 'x': 1, 'file': <
open file 'testfile', mode 'at' at 0x00B46C00>}
dup <__main__.B object at 0x00BEC7F0> {'y': 2, 'x': 1, 'file': <
open file 'testfile', mode 'at' at 0x00B46CA0>}
> I wonder if the logic inherent in the copy.deepcopy function could
> instead be implemented directly within object.__deepcopy__ (rather
> than the current model in which object does not have __deepcopy__).
> Then I would always have a means for simulating a call to
> deepcopy(self) based upon the super.__deepcopy__ logic.
> I wouldn't be surprised if I'm overlooking some undesirable
> consequence of such a major change in the model, but I don't see one
> upon first thought.
This deserves to be looked at with more detail. Try the python-ideas list,
or submit a RFE to http://bugs.python.org/
--
Gabriel Genellina
More information about the Python-list
mailing list