On Apr 23, 9:48 pm, Jeffrey Barish <[EMAIL PROTECTED]> wrote: > > Here it is: > > import copy > > class Test(int): > def __new__(cls, arg1, arg2): > return int.__new__(cls, arg1) > > def __init__(self, arg1, arg2): > self.arg2 = arg2 > > if __name__ == '__main__': > t = Test(0, 0) > t_copy = copy.copy(t)
First off, inheriting from a basic builtin type such as int and changing its constructor's signature is not typical; you should rethink your design unless you know what you're doing. One way to make this work is to define the special __copy__ method [1], specifying explicitly how to create a copy of a Test instance: class Test(int): ... def __copy__(self): return Test(int(self), self.arg2) The copy.copy() function looks for this special method and invokes it if it's defined. Normally (i.e. for pure Python classes that don't subclass a builtin other than object) copy.copy() is smart enough to know how to create a copy without an explicit __copy__ method, so in general you don't have to define it for every class that has to be copyable. > Traceback (most recent call last): > File "copytest.py", line 12, in <module> > t_copy = copy.copy(t) > File "/usr/lib/python2.5/copy.py", line 95, in copy > return _reconstruct(x, rv, 0) > File "/usr/lib/python2.5/copy.py", line 322, in _reconstruct > y = callable(*args) > File "/usr/lib/python2.5/copy_reg.py", line 92, in __newobj__ > return cls.__new__(cls, *args) > TypeError: __new__() takes exactly 3 arguments (2 given) The traceback is not obvious indeed. It turns out it involves calling the arcane __reduce_ex__ special method [2] defined for int, which returns a tuple of 5 items; the second is the tuple (<class '__main__.Test'>, 0) and these are the arguments passed to Test.__new__. So another way of fixing it is keep Test.__new__ compatible with int.__new__ by making optional all arguments after the first: class Test(int): def __new__(cls, arg1, arg2=None): return int.__new__(cls, arg1) # don't need to define __copy__ now from copy import copy t = Test(0, 0) assert copy(t) == t As a sidenote, your class works fine without changing anything when pickling/unpickling instead of copying, although pickle calls __reduce_ex__ too: from pickle import dumps,loads t = Test(0, 0) assert loads(dumps(t)) == t Perhaps someone more knowledgeable can explain the subtle differences between pickling and copying here. George [1] http://docs.python.org/lib/module-copy.html [2] http://docs.python.org/lib/node320.html -- http://mail.python.org/mailman/listinfo/python-list