2012-11-21 3 views
1

que je vois un comportement inhabituel en Python Dictionnaire:Changer une valeur dict change toutes les valeurs

import numpy as np 
td =[np.Inf, 2, 3] 
a = {} 
# First initialize contents of dictionary to a list of values 
for k in range(10): 
    a[k] = td 

#now I want to access the contents to modify them based on certain criteria 
for k in range(10): 
    c = a[k] 
    c[0] = k 
    a[k] = c 

A partir de ce que je me attends à chaque premier élément de la liste pour chaque valeur clé de dictionnaire à modifier en fonction de (c [0] = k), cependant, ce que je reçois à la fin est que toutes les valeurs du dictionnaire sont mis à jour à la dernière valeur de k: comme dans

{0: [9, 2, 3], 1: [9, 2, 3], 2: [9, 2, 3], 3: [9, 2, 3], 
4: [9, 2, 3], 5: [9, 2, 3], 6: [9, 2, 3], 7: [9, 2, 3], 
8: [9, 2, 3], 9: [9, 2, 3]} 

est-ce que je manque quelque chose, ou il y a quelque chose de mal dans la définition du dictionnaire? Je peux contourner ce problème de façon différente pour mon code, mais je m'intéresse à la raison pour laquelle la classe de dictionnaire se comporterait de cette façon.

Répondre

7

Parce que chaque touche obtient la même liste ... Pour faire une copie superficielle de la liste, utilisez la syntaxe suivante:

for k in range(10): 
    a[k] = td[:] 

Démo:

>>> d = {} 
>>> el = [1, 2, 3] 
>>> d[0] = el 
>>> d[1] = el 
>>> map(id, d.values()) 
[28358416, 28358416] 
+0

Merci, Mon impression était que la valeur de (td) serait réinitialisée à chaque fois, par exemple, ancienne valeur détruite, chaque nouvelle affectation, cependant, je sais maintenant que le dictionnaire se comporte différemment. :) – Nader

+0

@Nader ce n'est pas le dictionnaire .... Si vous avez fait 'mylist = []; pour i dans la plage (10): mylist.append (el) 'vous auriez la même chose :) –

+0

Je comprends que, cependant, je m'attendrais à ce que si je change la valeur de (el) à l'intérieur de la boucle, alors le la valeur ajoutée changerait en conséquence (par exemple mylist = []; pour i dans la plage (10): el = i; mylist.append (el)), ce qui est le cas dans ce cas, mais pas pour le dictionnaire. – Nader

0

Lorsque vous faites référence td Dans la ligne a[k] = td, vous ajoutez une référence à la liste d'origine. Toute modification de cette liste est visible partout où elle est référencée. Vous devez utiliser the copy module afin de faire une nouvelle liste (ou de construire une nouvelle liste pour chaque entrée, dans la boucle elle-même):

for k in range(10): 
    a[k] = [np.Inf, 2, 3] 
1

Ce qui se passe parce que lorsque vous insérez la valeur dans le dict, vous êtes ne pas insérer une nouvelle liste. Vous êtes en train d'insérer une référence à la même vieille liste. Ainsi, lorsque vous modifiez une valeur, vous changez la liste vers laquelle pointe la valeur, et donc la liste vers laquelle toutes les valeurs pointent.

Si vous voulez vraiment des listes séparées pour chaque valeur, alors vous feriez mieux de faire une copie superficielle de la liste au moment de l'insertion comme ceci:

td =[np.Inf, 2, 3] 
for k in range(10): 
    a[k] = td[:] #making a new list out of the old one 

Maintenant, cela fonctionnera de la façon dont vous attendez

for k in range(10): 
    c = a[k] 
    c[0] = k 
    a[k] = c 

Hope this helps

Questions connexes