Dear Gabriel, Thank you for your reply. As you guessed, I want to be able to select the method at runtime as in your final example, but when I tried your suggestion I got the same error (see below). I think the problem is that getattr is donig something different than in my example where I explicitly get it from the dict (see the very end of the transcript below):
--------------------------- Transcript Follows ---------------------------------------------------------- Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> # The following shows that using getattr to grab a method is >>> # incompatible with copy.deepcopy >>> class a: ... def foo(self): pass ... >>> class b(a): ... def __init__(self): ... self.x = getattr(a,'foo') ... >>> import copy >>> c=b() >>> copy.deepcopy(c) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "c:\Python25\lib\copy.py", line 162, in deepcopy y = copier(x, memo) File "c:\Python25\lib\copy.py", line 291, in _deepcopy_inst state = deepcopy(state, memo) File "c:\Python25\lib\copy.py", line 162, in deepcopy y = copier(x, memo) File "c:\Python25\lib\copy.py", line 254, in _deepcopy_dict y[deepcopy(key, memo)] = deepcopy(value, memo) File "c:\Python25\lib\copy.py", line 189, in deepcopy y = _reconstruct(x, rv, 1, memo) File "c:\Python25\lib\copy.py", line 322, in _reconstruct y = callable(*args) File "c:\Python25\lib\copy_reg.py", line 92, in __newobj__ return cls.__new__(cls, *args) TypeError: instancemethod expected at least 2 arguments, got 0 >>> >>> # The following shows that getattr is doing something different >>> # than looking in the __dict__ of base classes >>> b.__bases__[0].__dict__['foo'] <function foo at 0x009F0CF0> >>> getattr(a,'foo') <unbound method a.foo> >>> On Jan 4, 10:08 pm, Gabriel Genellina <[EMAIL PROTECTED]> wrote: > At Thursday 4/1/2007 17:26, Emin wrote: > > >I got some unexpected behavior in getattr and copy.deepcopy (see > >transcript below). I'm not sure if this is actually a bug in > >copy.deepcopy or if I'm doing something too magical with getattr. > >Comments would be appreciated.Both examples are different. #1 stores a > >*bound* method into an > instance attribute. Bound methods carry a reference to "self", this > creates a cyclic reference that may cause problems to the garbage > collector (and confuses deepcopy, apparently). > #2 uses and *unbound* method and it's the usual way. > > > >>> class a: > >... def foo(self): > >... print 'hi' > >... > > >>> class b(a): #1 > >... def __init__(self): > >... self.y = getattr(self,'foo') > > > >>> class b(a): #2 > >... def __init__(self): > >... self.x = self.__class__.__bases__[0].__dict__['foo']For #2 > >you can simply say: > > class b(a): > x = a.foo > > If you have to choose at runtime (a simplified version of your own code): > > class b(a): > def __init__(self): > name = select_method_to_use(..., default="foo") > self.x = getattr(a, name) > > You *know* your bases because you wrote them in the class statement > (or use super() instead of playing with __bases__); and getattr works > fine here so you don't need to mess with the __dict__ details. > > (Note that #1 was *almost* right, you had to replace self by the base class) > > -- > Gabriel Genellina > Softlab SRL > > __________________________________________________ > Preguntá. Respondé. Descubrí. > Todo lo que querías saber, y lo que ni imaginabas, > está en Yahoo! Respuestas (Beta). > ¡Probalo ya!http://www.yahoo.com.ar/respuestas -- http://mail.python.org/mailman/listinfo/python-list