Copy.deepcopy raises a TypeError for objects with a self-defined __new __ () method

I want to implement a character type that tracks the characters we already have (stored 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 the list of such Symbol instances, an exception is thrown:

 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 to make a deep copy of these objects using the __new__ self- __new__ methods?
  • And any suggestions on when and how to use copy.deepcopy ?

Thank you so much!

+8
python deep-copy
source share
3 answers

one problem is that deepcopy and copy have no way of knowing which arguments are passed to __new__ , so they only work with classes that don't need constructor arguments.

the reason you can have __init__ arguments is because __init__ not called when copying an object, but __new__ must be called to create a new object.

therefore, if you want to control copying, you will need to define special methods __copy__ and __deepcopy__ :

 def __copy__(self): return self def __deepcopy__(self, memo): return self 

By the way, singletons are evil and not really needed in python.

+5
source share

I think you want instances of Symbol to be single. Deepcopy, however, is supposed to be used when you need an exact copy of an instance, i.e. Another instance that is equal to the original.

Thus, the use of the genus here is contrary to the purpose of the profound. If you want to make it work, you can define the __ deepcopy__ method on Symbol.

+1
source share

Define __getnewargs__ - this way you can not only copy and deepcopy , but you can also pickle .

0
source share

All Articles