En Mon, 01 Jun 2009 14:19:19 -0300, Michael H. Goldwasser
<goldw...@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
--
http://mail.python.org/mailman/listinfo/python-list