copy.deepcopy raises TypeError on objects with self-defined __new__() method
deep-copy, python
Solution
one problem is that `deepcopy` and `copy` have no way of knowing which arguments to pass to `__new__`, therefore they only work with classes that don't require constructor arguments.
the reason why you can have `__init__` arguments is that `__init__` isn't called when copying an object, but `__new__` must be called to create the new object.
so if you want to control copying, you'll have to define the special `__copy__` and `__deepcopy__` methods:
def __copy__(self):
return self
def __deepcopy__(self, memo):
return self
by the way, singletons are evil and not really needed in python.
Problem
I want to implement a symbol type, which keeps track of the symbols we already have(saved in `_sym_table`), and return them if they exist, or create new ones otherwise. The code: ``` # -*- coding: utf-8 -*- _sym_table = {} class Symbol(object): def __new__(cls, sym): if sym not in _sym_table: return super().__new__(cls) else: return _sym_table[sym] def __init__(self, sym): self.sym = sym _sym_table[sym] = self def __str__(self): return self.sym def __cmp__(self, other): return self is other def __hash__(self): return self.sym.__hash__() ``` But when I call `copy.deepcopy` on a list of such `Symbol` instances, exception is raised: ``` a = Symbol('a') b = Symbol('b') s = [a, b] t = copy.deepcopy(s) ``` Error messages: ``` Traceback (most recent call last): File "xxx.py", line 7, in <module> t = copy.deepcopy(s) File "/usr/lib/python3.2/copy.py", line 147, in deepcopy y = copier(x, memo) File "/usr/lib/python3.2/copy.py", line 209, in _deepcopy_list y.append(deepcopy(a, memo)) File "/usr/lib/python3.2/copy.py", line 174, in deepcopy y = _reconstruct(x, rv, 1, memo) File "/usr/lib/python3.2/copy.py", line 285, in _reconstruct y = callable(*args) File "/usr/lib/python3.2/copyreg.py", line 88, in __newobj__ return cls.__new__(cls, *args) TypeError: __new__() takes exactly 2 arguments (1 given) ``` So my questions are: - How can I make a deep copy on these objects with self-defined `__new__` methods? - And any suggestions about when and how to use `copy.deepcopy`? Thanks a lot!