2010-08-14 12 views
2
tokens_raw = {"foo": "bar"} 
tokens_raw_old = { } 
while not tokens_raw == tokens_raw_old: 
    tokens_raw_old = tokens_raw 
    # while loop that modifies tokens_raw goes here; 
    # tokens_raw_old is never referenced 
    print tokens_raw_old == tokens_raw 

Cette sortie True après la première fois pour une raison quelconque. tokens_raw_old a les mêmes données que tokens_raw, même après tokens_raw seul a été modifié. Ai-je fait une erreur stupide quelque part, ou le problème réside-t-il dans la seconde boucle while (qui, une fois de plus, ne fait jamais référence à tokens_raw_old)? S'il n'y a pas d'erreurs évidentes, je posterai plus de code.Pourquoi cette variable est-elle modifiée?

Répondre

7

tokens_raw_old = tokens_raw signifie: faire une nouvelle référence appelée token_raw_old à l'même objet auquel se réfère le nom tokens_raw à ce moment. C'est le même objet, pas une copie de l'objet! Ainsi, les changements apportés à ce seul et unique objet à travers l'une des références affectent évidemment le même objet lorsqu'on l'examine à travers l'autre référence.

Si vous souhaitez une copie, demandez-en une copie! Par exemple, étant donné que tokens_raw est un dict avec des valeurs immuables (et les clés, mais c'est fréquent dans les dicts):

tokens_raw_old = tokens_raw.copy() 

sera suffisant. Identiquement (juste une question de style), il en sera

tokens_raw_old = dict(tokens_raw) 

(faire une copie par « appeler le type en tant que constructeur de copie », un concept qui fait appel à des programmeurs C++ - dont je suis l'un, donc je aime vraiment ce formulaire ;-).

Si vous devez couvrir pour un cas général (tokens_raw d'être de nombreux possibles différents types, ou des valeurs dans étant peut-être modifié):

import copy 

tokens_raw_old = copy.deepcopy(tokens_raw) 

Cela peut être très lent, mais, « quand vous avez besoin il, vous en avez besoin "- il fait profonde copie de l'objet, c'est-à-dire, il ne copie pas simplement le conteneur mais aussi tous les objets contenus (récursivement, si un conteneur contient d'autres conteneurs - disons trois fois vite...;-). Tous les objets ne peuvent pas être copiés (profondément ou superficiellement) - par exemple, un objet de fichier ouvert ne peut pas être copié (vous avez besoin d'autres approches si vous avez des besoins aussi bizarres et avancés). Mais, pour une dictée avec des cordes comme des clés et des valeurs, les approches simples que j'ai mentionnées au début de cette réponse suffiront, et être assez rapide aussi ;-).

+0

J'ai effectivement fait une erreur dans le code que j'ai collé; tokens_raw est une liste, pas une dict, donc .copy() n'est pas une méthode valide. Cependant, la réponse a encore du sens, et j'ai trouvé que l'utilisation de 'tokens_raw_old = tokens_raw [:]' a le même effet que ce que vous avez suggéré. Merci pour l'aide. :) – Fraxtil

+1

@Fraxtil, bien sûr, mais personnellement, je déteste le toujours populaire 'somelist [:]' idiome - 'liste (somelist)' est juste ** tellement ** beaucoup plus lisible comme un moyen de copier peu profonde une liste (ou, faire une version de liste de n'importe quelle séquence d'entrée, d'ailleurs). Eh bien, question de style, je suppose! -) –