Pergunta

Tenho vindo a utilizar este método de cópia por um bom tempo, em muitas classes que precisava.

class population (list):
def __init__ (self):
    pass

def copy(self):
    return copy.deepcopy(self)

Tem de repente começou a produzir este erro:

     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__()
>>> 

as linhas que incluem as referências a linhas 338, 162, 255, 189 foram repetidas algumas vezes antes da 'linha 338' que eu copiei aqui.

Foi útil?

Solução

Você clonagem de um gerador? Geradores não pode ser clonado.

Copiar resposta por Gabriel Genellina aqui:


Não há nenhuma maneira de "clonagem" de um gerador:

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>

Você pode fazer isso com uma função de gerador porque ele atua como um "gerador
fábrica", a construção de um novo gerador quando chamado. Mesmo usando o Python C
API, para criar um gerador precisa de um objeto frame - e não há nenhuma maneira
para criar um objeto frame "on the fly" que eu conheço: (

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 e g2 compartilham o mesmo quadro de execução, de modo que eles não são independentes. há
há nenhuma maneira fácil de criar um novo quadro em Python:

py> type(g.gi_frame)()
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
TypeError: cannot create 'frame' instances

Um pode tentar usar PyFrame_New - mas isso é muito mágica para o meu gosto ...

Outras dicas

Isto ocorre em muitos casos quando um acidentalmente tenta clonar o iterador para uma classe. Por exemplo, em PIL, tentando clonar o PixelAccess de um Image lançará este erro.

Tome um exemplo onde pixels = image.load(). Em vez de tentar fazer algo como pixels_copy = copy.copy(pixels), você tem que copiar o objeto base e, em seguida, produzir um iterador. Então, substitua aquele pedaço de código com pixels_copy = image.copy().load().

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top