On Fri, 11 Feb 2005 21:22:35 +1000, Nick Coghlan <[EMAIL PROTECTED]> wrote:
>
>Interesting. The problem appears to be that bound methods are not copyable:
>
Curiosity got the better of me and I started diggin about in copy.py. Turns out that return values of reductors for functions don't include a code object or global dict, and reductors for instancemethods don't return a function or instance, hence the complaint that instancemethod (or function, as below) didn't get enough arguments.


 >>> f = Foo('foo')
 >>> fbrc,fbargs = f.bar.__reduce_ex__(2)[:2]
 >>> fbargs
(<type 'instancemethod'>,)
 >>> fbrc(*fbargs)
 Traceback (most recent call last):
   File "<pyshell#2>", line 1, in -toplevel-
     fbrc(*fbargs)
   File "C:\DEVEL\PYTHON\2.4\lib\copy_reg.py", line 92, in __newobj__
     return cls.__new__(cls, *args)
 TypeError: instancemethod expected at least 2 arguments, got 0
 >>> fbrc(fbargs[0], f.bar, f, type(f))
<bound method Foo.bar of Foo([f,o,o])>
 >>> def bar(a, b):
     return (a,b)
 >>> info = bar.__reduce_ex__(2)
 >>> rc,args = info[:2]
 >>> args
 (<type 'function'>,)
 >>> rc(*args)
 Traceback (most recent call last):
   File "<pyshell#9>", line 1, in -toplevel-
     rc(*args)
   File "C:\DEVEL\PYTHON\2.4\lib\copy_reg.py", line 92, in __newobj__
     return cls.__new__(cls, *args)
 TypeError: function() takes at least 2 arguments (0 given)
 >>> baz=rc(args[0], bar.func_code, bar.func_globals)
 >>> baz(1,2)
 (1,2)

Note 'args' is not something like :
 (<type 'function'>, <function bar at 0xXXXXXXXX>, { ... })

As an aside, what is the tuple returned by a reductor called? What are its components called?

>Normally, the methods live in the class dictionary, so they don't cause a
>problem with copying the instance.
>
But a dynamically assigned instance method lives in the intance dictionary, making deepcopy choke when it deepcopies the instance state. That makes sense now.


>It turns out this exception actually makes sense, since you *don't* want to copy
>these atributes to the new instance. If you actually copied them, they'd be
>bound to the *old* instance, rather than the new one.
>
True. It wouldn't cause a problem within my __init__, since the attribute is reassigned after the deepcopy, though should anyone else deepcopy an instance... Definitely better that the deepcopy throws the TypeError. But why shouldn't we be able to copy a non-method function?


>So I expect you'll need to provide a __deepcopy__ in order to correctly generate
>the instancemethods bound to the new instance.
>
That's what I've decided, too.
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to