2009-09-09 6 views
3

J'ai utilisé cette méthode de copie pendant un certain temps, dans beaucoup de classes qui en avaient besoin.Python: copy.deepcopy génère une erreur

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

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

Il a soudainement commencé à produire cette erreur:

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

les lignes qui incluent les références aux lignes 338, 162, 255, 189 ont été répétées un certain nombre de fois avant la « ligne 338 » qui J'ai copié ici.

Répondre

9

Êtes-vous en train de cloner un générateur? Generators can't be cloned.

réponse de copie par Gabriel Genellina ici:


Il n'y a aucun moyen de "clonage" un générateur:

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> 

Vous pouvez le faire avec une fonction de générateur, car il agit en tant que "générateur
usine", la construction d'un nouveau générateur lorsqu'il est appelé. Même en utilisant l'API Python C
, pour créer un générateur on a besoin d'un objet cadre - et il n'y a aucun moyen
pour créer un objet cadre « à la volée » que je connais :(

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 et part g2 le même cadre d'exécution, de sorte qu'ils ne sont pas indépendants Il
est pas facile de créer un nouveau cadre en Python:

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

On pourrait essayer d'utiliser PyFrame_New - mais c'est trop magique. à mon goût ...

+0

Je suis nouveau à ce sujet, et je venais d'essayer d'utiliser un «rendement». Donc, je ferais mieux de lire plus sur eux. Oui, quand j'ai supprimé le 'rendement', l'erreur est partie. Merci –

+0

Semble que le lien est mort. – antonagestam

+0

@antonagestam Fixé. – wRAR

0

Cela se produit dans de nombreux cas lorsque l'on tente accidentellement de cloner l'itérateur vers une classe. Par exemple, dans PIL, essayer de cloner le PixelAccess d'un Image va lancer cette erreur.

Prenez un exemple où pixels = image.load(). Au lieu d'essayer de faire quelque chose comme pixels_copy = copy.copy(pixels), vous devez copier l'objet de base et ensuite produire un itérateur. Donc, remplacez ce morceau de code par pixels_copy = image.copy().load().

Questions connexes