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

Reply via email to