我想实现一个符号类型,它跟踪我们已经拥有的符号(保存在_sym_table
中),如果它们存在则返回它们,否则创建新符号。代码:
# -*- 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__()
但是当我在copy.deepcopy
个Symbol
个实例的列表上调用a = Symbol('a')
b = Symbol('b')
s = [a, b]
t = copy.deepcopy(s)
时,会引发异常:
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)
错误讯息:
__new__
所以我的问题是:
copy.deepcopy
方法对这些对象进行深层复制? 非常感谢!
答案 0 :(得分:7)
一个问题是deepcopy
和copy
无法知道传递给__new__
的参数,因此它们只适用于不需要构造函数参数的类。
您可以拥有__init__
参数的原因是复制对象时未调用__init__
,但必须调用__new__
来创建新对象。
因此,如果您想控制复制,则必须定义特殊的__copy__
和__deepcopy__
方法:
def __copy__(self):
return self
def __deepcopy__(self, memo):
return self
顺便说一下,singletons是evil,在python中并不是真的需要。
答案 1 :(得分:1)
在我看来,你希望Symbol实例是单例。但是,当您需要实例的精确副本(即与原始实例相同的其他实例)时,应该使用Deepcopy。
因此,这里的用法与深度复制的目的相矛盾。如果你想让它无论如何都可以工作,你可以在 Symbol 上定义__deepcopy__方法。
答案 2 :(得分:0)
定义__getnewargs__
- 这样您不仅可以copy
和deepcopy
,还可以pickle
。