Python: copy.deepcopy 产生错误
我已经在很多需要这个复制方法的类里用了很长一段时间了。
class population (list):
def __init__ (self):
pass
def copy(self):
return copy.deepcopy(self)
但最近它突然开始出现这个错误:
File "C:\Python26\lib\copy.py", line 338, in _reconstruct
state = deepcopy(state, memo)
File "C:\Python26\lib\copy.py", line 162, in deepcopy
y = copier(x, memo)
File "C:\Python26\lib\copy.py", line 255, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
File "C:\Python26\lib\copy.py", line 189, in deepcopy
y = _reconstruct(x, rv, 1, memo)
File "C:\Python26\lib\copy.py", line 323, in _reconstruct
y = callable(*args)
File "C:\Python26\lib\copy_reg.py", line 93, in __newobj__
return cls.__new__(cls, *args)
TypeError: object.__new__(generator) is not safe, use generator.__new__()
>>>
提到的338、162、255和189行的内容在我复制的'338行'之前重复了很多次。
2 个回答
0
这个问题经常发生在不小心尝试复制一个类的迭代器时。例如,在PIL库中,试图复制一个Image
的PixelAccess
时就会出现这个错误。
举个例子,假设你有一行代码是pixels = image.load()
。你不能直接用pixels_copy = copy.copy(pixels)
来复制它,而是需要先复制基础对象,然后再生成一个迭代器。所以,你应该把那段代码改成pixels_copy = image.copy().load()
。
9
你在克隆一个生成器吗? 生成器是不能被克隆的。
这里是Gabriel Genellina的回答:
没有办法“克隆”一个生成器:
py> g = (i for i in [1,2,3])
py> type(g)()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'generator' instances
py> g.gi_code = code
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: readonly attribute
py> import copy
py> copy.copy(g)
Traceback (most recent call last):
...
TypeError: object.__new__(generator) is not safe, use generator.__new__()
py> type(g).__new__
<built-in method __new__ of type object at 0x1E1CA560>
你可以用生成器函数来做到这一点,因为它就像一个“生成器工厂”,每次调用时都会生成一个新的生成器。即使使用Python的C接口,创建一个生成器也需要一个框架对象——而我知道的没有办法“即时”创建一个框架对象 :(
py> import ctypes
py> PyGen_New = ctypes.pythonapi.PyGen_New
py> PyGen_New.argtypes = [ctypes.py_object]
py> PyGen_New.restype = ctypes.py_object
py> g = (i for i in [1,2,3])
py> g2 = PyGen_New(g.gi_frame)
py> g2.gi_code is g.gi_code
True
py> g2.gi_frame is g.gi_frame
True
py> g.next()
1
py> g2.next()
2
g和g2共享同一个执行框架,所以它们并不是独立的。在Python中,没有简单的方法可以创建一个新的框架:
py> type(g.gi_frame)()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'frame' instances
可以尝试使用PyFrame_New——但对我来说,这实在是太神奇了……