2012-11-21 47 views
1

我看到在Python解釋一些不尋常的行爲的所有值:改變基於(C改變一個字典值改變

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 

從這個我期望列表中爲每個字典鍵值的每個第一項[0] = K),但是,我所得到的到底是什麼字典的所有值都被更新爲k的最後一個值:在

{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]} 

我缺少的東西,或有什麼不對在字典中的定義? 我可以以不同的方式解決這個問題,以便讓我的代碼運行,但是我對字典類爲什麼會這樣運行感興趣。

回答

7

由於每個按鍵得到同一列表 ...爲了讓列表的淺表副本,請使用以下語法:

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

演示:

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

謝謝你,我的印象是,(TD)的價值將被重新初始化每一次,即舊值被毀,每一個新的任務,不過,我現在的認識字典的行爲有所不同。 :) – Nader

+0

@Nader它不是字典....如果你做了'mylist = [];對於我在範圍內(10):mylist.append(el)'你會有同樣的東西:) –

+0

我明白,但是,如果我改變循環內部(el)的值,我會期待如果附加值會相應地改變(例如,mylist = [];對於範圍(10)中的i:el = i; mylist.append(el)),在這種情況下它是這樣做的,但不適用於字典。 – Nader

0

當您引用td在行a[k] = td中,實際上是將引用附加到原始列表。無論在何處引用,該列表的任何修改都是可見的。你需要爲了使新的列表中使用the copy module(或建立一個新的列表中的每個條目,在循環本身):

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

,因爲當你插入值到dict這是發生,你是沒有插入一個全新的名單。您實際上是插入對同一個舊列表的引用。因此,當您更改一個值時,實際上是在更改值指向的列表,因此也是所有值指向的列表。

如果你真的想爲每個值單獨的列表,然後你會更好上榜的淺表副本在插入時,像這樣:

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

現在,這會工作,你希望的方式

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

希望這有助於