473,722 Members | 2,216 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

deepcopy chokes with TypeError on dynamically assigned instance method

(see end of message for example code)

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". Tested with Python 2.3.4 on
OpenBSD and Python 2.4 on Win98; same results. Is this a bug in
deepcopy, how I dynamically assign the instance method or something
else? (See example code for how I did it.)

If you're curious as to why the deep copy and dynamic assign are
necessary or have implementation suggestions (or alternatives), I bet
you'd like some details. The TypeError cropped up while coding a
'Point' class representing cartesian coordinates. I needed to
overload an 'origin' method as both a class method and an instance
method (if Python were more Perlesque... ;-) ). 'origin' returns a
point representing an origin. The class method requires an argument
for the dimension of the origin, while the instance method uses the
dimension of an instance (ortus overloading). As the instance
reference isn't bound when the class 'origin' method is defined,
there's no way to use a default argument. I instead dynamically
assign an instance method to the 'origin' attribute of the instance.

As for the deepcopy, scalars aren't necessarily of a built-in numeric
type, though I generally expect them to be numeric (you could use
lists or strings as scalars, but not many methods would still be
usable). Point is the base clase for Vector, and I want (e.g.)
vectors of vectors so I can eventually extend Vector to Matrix and
Tensor. The Point constructor has a single argument: a sequence of
scalars (which, as noted, can be sequences). In practice, the
sequence itself will be a tuple, a list, a Point or descendant of
Point (so that Point can act as a copy constructor). To prevent a
copied point from aliasing elements of a different Point, I used
deepcopy. When the TypeError struck, I switched to a generator, which
works as long as every constructor functions as a copy constructor
(not necessarily true, apparently, of lists, but true of Points). I
could also implement copy-on-write semantics for coordinates or
implement __deepcopy__ for Point (which will probably be the final
solution).
example code:

from copy import copy,deepcopy
import new

class Foo(list):
"Foo"

def __init__(self, l=[]):
list.__init__(s elf, deepcopy(l))
# using generator rather than deepcopy produces no errors.
#list.__init__( self, [copy(el) for el in l])
# 'copy(el)' in generator results in a deepcopy of sequence
# as long as each object encountered uses a copy constructor
# (which I expect of numeric types) and doesn't implement
# a shallow __copy__. Alternative is to use type(el)(el):
#list.__init__( self, [type(el)(el) for el in l])
def bar(self):
return 'bar'
self.bar=new.in stancemethod(ba r, self, self.__class__)
# also causes deepcopy to choke:
#self.bar = self._bar

def _bar(self):
return 'bar'

#deepcopy has no problem with this
bar = _bar

def __repr__(self):
return self.__class__. __name__+'(['\
+','.join(map(s tr, self))+'])'

# causes deepcopy to throw a TypeError
Foo(Foo('foo'))

Jul 18 '05 #1
7 3969
5ÛHH575-UAZWKVVP-7H2H48V3 wrote:
class Foo(list):
"Foo"

def __init__(self, l=[]):


Change this too:
def __init__(self, l=None):
if l is None: l = []
And see if your problem goes away.

Cheers,
Nick.

--
Nick Coghlan | nc******@email. com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
Jul 18 '05 #2
On Thu, 10 Feb 2005 23:50:09 +1000, Nick Coghlan
<nc******@iinet .net.au> wrote:
def __init__(self, l=[]):


Change this too:
def __init__(self, l=None):
if l is None: l = []


Same error. The only ways of not getting the TypeError I've found are
not to call deepcopy or not assign an instancemethod to an instance
attribute (assigning an instancemethod to a class attribute is fine).
Jul 18 '05 #3
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.
Jul 18 '05 #4
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\li b\copy.py", line 95, in copy
return _reconstruct(x, rv, 0)
File "C:\Python24\li b\copy.py", line 320, in _reconstruct
y = callable(*args)
File "C:\Python24\li b\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\li b\copy.py", line 95, in copy
return _reconstruct(x, rv, 0)
File "C:\Python24\li b\copy.py", line 320, in _reconstruct
y = callable(*args)
File "C:\Python24\li b\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 | nc******@email. com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
Jul 18 '05 #5
On Fri, 11 Feb 2005 21:22:35 +1000, Nick Coghlan <nc******@iinet .net.au>
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\PYTHO N\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\PYTHO N\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_global s)
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 copythese atributes to the new instance. If you actually copied them, they'd bebound 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 generatethe instancemethods bound to the new instance.

That's what I've decided, too.
Jul 18 '05 #6
"@t comcast d.t net <"@bag.python.o rg wrote:
As an aside, what is the tuple returned by a reductor called? What are
its components called?
Ya got me. Alex might have a name for it :)
>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.


Yup.
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?


I honestly don't know, although I'm hard-pressed to see how doing so would ever
be *useful*. Duplicating *parts* of a function would seem to make sense (to
build a new function which is similar, but not identical), but duplicating the
whole thing seems rather pointless. Although I guess you could just pickle it
and then unpickle the result to make a copy :)

Again, Alex Martelli or someone else more familiar with the guts of copy.py than
I am might be able to give a better answer if they happen to see the question.

Cheers,
Nick.

--
Nick Coghlan | nc******@email. com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
Jul 18 '05 #7
On Sun, 13 Feb 2005 12:01:42 +1000, Nick Coghlan
<nc******@iinet .net.au> wrote:
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?


I honestly don't know, although I'm hard-pressed to see how doing so would ever
be *useful*. Duplicating *parts* of a function would seem to make sense (to
build a new function which is similar, but not identical), but duplicating the
whole thing seems rather pointless. Although I guess you could just pickle it
and then unpickle the result to make a copy :)

It's not so much that copying a function is useful as it would be nice
if copy and deepcopy didn't fail on plain functions, as there are
cases where objects would need to store references to such functions.
Imagine classes implementing operations on functions such as numeric
differentiation and integration (while symbolic differentiation &
integration would probably be better for production code, the example
still stands). As it is, a little extra work would be needed to
support deepcopying such classes. And it's always nice to avoid work.

Thanks for your help and feedback on this.
Jul 18 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
1883
by: OKB (not okblacke) | last post by:
I've noticed some peculiar behavior from copy.deepcopy: if you pass it a method or function object, it raises a TypeError somewhere in copy_reg saying "function() takes at least 2 arguments (0 given)". I'm guessing this is the constructor for functions, and it's somehow being incorrectly called, but I'm not really sure. This behavior is annoying, however. I realize the deepcopy documentation warns that it doesn't handle copying certain...
1
3860
by: Newgene | last post by:
Hi, group, I am trying to dynamically add a method to class by following this post: http://groups-beta.google.com/group/comp.lang.python/browse_thread/thread/2ec2ad7a0a5d54a1/928e91be352c6bfc?q=%22new.code(%22+%22import+new&_done=%2Fgroup%2Fcomp.lang.python%2Fsearch%3Fgroup%3Dcomp.lang.python%26q%3D%22new.code(%22+%22import+new%26qt_g%3D1%26&_doneTitle=Back+to+Search&&d#928e91be352c6bfc But I got the Error like the below: ...
0
1411
by: Stefan Behnel | last post by:
Hi! I just stumbled over this: ..>>> class test(object): .... def t(): pass .... t.testval = 1 .... ..>>> test.t
4
7174
by: Materialised | last post by:
Hi All, I have a strange issue, and I am not sure if it is a error on my part, or a visual studio bug. I am using VS.Net 2003 Enterprise. I have 2 event handlers as follows: Public Shared Sub txtFace1_DoubleClick(ByVal sender As Object, ByVal e
4
2113
by: MuZZy | last post by:
Hi, I'm retouching some utility classes used everywhere across our app, and there are certain methods used everywhere and pretty frequently. I'm changing them from instance methods to static ones, so to use them you don't need to create an instance of that utility class. So my question is - is there any difference/danger of using a static method vs instance method.
0
1229
by: t.lehmann | last post by:
I know about the problem about the standard: "you can not cast a method to another type!" There's a command class wrapping an instance and it's method; the command is a shared pointer to a base class of concrete template classes being able to adapt methods 0 - 3 parameters. The template functions 'make_command' are creating the right implementations - hidden to you.... - automatically deleted when leaving scope.... goal:
0
1393
by: mkadasi | last post by:
I want to dynamically create instance of class stored in other application. I am writing the following code for this purpose: Here in the AssemblyFunc() I am loading the assembly of TariffClass application which is loaded successfully. In objectCreate() I am creating object of class present in TariffClass application. But I am getting the following error 'Could not load file or assembly 'file:///C:\Inetpub\wwwroot\QuickQuote\TariffClass,...
2
1636
by: Danny | last post by:
howdy, I have created an instance method for an object using new.instancemethod. It works great. Now the questions are: 1) how do I dynamically inspect an object to determine if it has an instance method? (there is a class method with the same name) 2) how do I dynamically delete the instance method?
0
1043
by: Maric Michaud | last post by:
Le Friday 05 September 2008 17:29:39 mercado mercado, vous avez écrit : Note that "self" for somemethod is just a local variable of the calling function. You cannot retrieve those local variables without playing with the call stack, and this reveal generally a bad design (except for inspection purpose). You have two common solutions here : - the simplest is to pass the instance of bar or again to the foo constructor or as...
0
8860
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8738
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9381
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
9151
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
6680
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5994
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4762
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3207
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2600
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.