deepcopy chokes with TypeError on dynamically assigned instance method

Nick Coghlan ncoghlan at iinet.net.au
Fri Feb 11 06:22:35 EST 2005


Kanenas wrote:
> On Thu, 10 Feb 2005 00:54:04 -0800, Kanenas <kanenas @t comcast d.t
> net> wrote:
> 
> 
>>When an instance has a dynamically assigned instance method, deepcopy
>>throws a TypeError with the message "TypeError: instancemethod
>>expected at least 2 arguments, got 0".  
> 
> 
> I forgot to mention that the TypeError is thrown only when
> constructing an instance from another instance in the same class, e.g.
> Foo('bar') is fine but Foo(Foo('bar')) will fail.

Interesting. The problem appears to be that bound methods are not copyable:

 >>> x = Foo('bar')
 >>> x
Foo([b,a,r])
 >>> x.bar
<bound method Foo.bar of Foo([b,a,r])>
 >>> copy(x.bar)
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "C:\Python24\lib\copy.py", line 95, in copy
     return _reconstruct(x, rv, 0)
   File "C:\Python24\lib\copy.py", line 320, in _reconstruct
     y = callable(*args)
   File "C:\Python24\lib\copy_reg.py", line 92, in __newobj__
     return cls.__new__(cls, *args)
TypeError: instancemethod expected at least 2 arguments, got 0
 >>> x.__repr__
<bound method Foo.__repr__ of Foo([b,a,r])>
 >>> copy(x.__repr__)
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "C:\Python24\lib\copy.py", line 95, in copy
     return _reconstruct(x, rv, 0)
   File "C:\Python24\lib\copy.py", line 320, in _reconstruct
     y = callable(*args)
   File "C:\Python24\lib\copy_reg.py", line 92, in __newobj__
     return cls.__new__(cls, *args)
TypeError: instancemethod expected at least 2 arguments, got 0

Normally, the methods live in the class dictionary, so they don't cause a 
problem with copying the instance.

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.

So I expect you'll need to provide a __deepcopy__ in order to correctly generate 
the instancemethods bound to the new instance.

I also realised that the reason the use of a mutable default is OK here is 
because you're deepcopying it.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at email.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://boredomandlaziness.skystorm.net



More information about the Python-list mailing list