copy.deepcopy使用自定义__new __()方法在对象上引发TypeError [英] copy.deepcopy raises TypeError on objects with self-defined __new__() method
问题描述
我想实现一个符号类型,该符号类型跟踪我们已经拥有的符号(保存在 _sym_table
中),如果存在则返回它们,或者创建新的除此以外。代码:
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__()
但是当我在此类 Symbol
实例的列表中调用 copy.deepcopy
时,会引发异常:
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)
错误消息:
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 __ $ c $对这些对象进行深层复制c>方法?
- 以及有关何时以及如何使用
copy.deepcopy
的任何建议?
- 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
?
非常感谢!
推荐答案
一个问题是 deepcopy
和 copy
无法知道将哪些参数传递给 __ new __
,因此它们仅适用于不需要构造函数参数的类。
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.
拥有 __ init __
参数是在复制对象时不会调用 __ init __
,而是 __ new __
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.
因此,如果要控制复制,则必须定义特殊的 __ copy __
和 __ deepcopy __
方法:
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.
这篇关于copy.deepcopy使用自定义__new __()方法在对象上引发TypeError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!