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», которую я здесь скопировал.
Решение
Ты клонируешь генератор? Генераторы не могут быть клонированы.
Копирование ответа Габриэля Генеллина здесь:
<Ч>Нет способа "клонировать" генератор:
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
API, для создания генератора нужен рамочный объект - и нет способа
создать рамочный объект «на лету» что я знаю: (
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 - но на мой вкус это слишком волшебно ...
Другие советы
Это происходит во многих случаях, когда кто-то случайно пытается клонировать итератор в класс. Например, в PIL попытка клонировать PixelAccess
Image
приведет к этой ошибке. Р>
Возьмите пример, где пиксели = image.load ()
. Вместо того, чтобы пытаться сделать что-то вроде pix_copy = copy.copy (пиксели)
, вы должны скопировать базовый объект и затем создать итератор. Поэтому замените этот фрагмент кода на пиксель_сопии = image.copy (). Load ()
.