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:
__new__
methods? copy.deepcopy
? Thanks a lot!
copy() create reference to original object. If you change copied object - you change the original object. . deepcopy() creates new object and does real copying of original object to new one. Changing new deepcopied object doesn't affect original object.
To make a deep copy, use the deepcopy() function of the copy module. In a deep copy, copies are inserted instead of references to objects, so changing one does not change the other.
3 Things to Remember. Making a shallow copy of an object won't clone child objects. Therefore, the copy is not fully independent of the original. A deep copy of an object will recursively clone child objects. The clone is fully independent of the original, but creating a deep copy is slower.
In Shallow copy, a copy of the original object is stored and only the reference address is finally copied. In Deep copy, the copy of the original object and the repetitive copies both are stored.
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.
Seems to me you want the Symbol instances to be singletons. Deepcopy, however is supposed to be used when you want an exact copy of an instance, i.e. a different instance that is equal to the original.
So the usage here kinda contradicts the purpose of deepcopy. If you want to make it work anyhow, you can define the __deepcopy__ method on Symbol.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With