2016-11-20 98 views
-1

我不明白Python的2.7.12的這種行爲......爲什麼列表中變量的值在Python中更改?

請驗證代碼,粘貼下面:

test = [(('AAA_1', 'BBB_1', 'CCC_1'), 1), (('AAA_2', 'BBB_2', 'CCC_2'), 2),(('AAA_3', 'BBB_3', 'CCC_3'), 3), (('AAA_4', 'BBB_4', 'CCC_4'), 4)] 
for i, j in enumerate(test): 
    for k, l in enumerate(j[0]): 
     if k == 0: 
      dc['first'] = l 
     elif k == 1: 
      dc['second'] = l 
     elif k == 2: 
      dc['third'] = l 
     elif k == 3: 
      dc['fourth'] = l 
    c.append(dc) 
    print "/n" 
    print "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXx" 
    print dc 
    print json.dumps(c, indent=1) 
    print c 

print json.dumps(c, indent=1) 

上面顯示的代碼的結果存儲在公共引擎收錄:http://pastebin.com/GkrTyseg

對我來說什麼是奇怪的: 通過附加列表:c我想收到詞典列表。這些字典可能代表每種類型的AAA,BBB,CCC元組。我使用字典將其轉換爲json,以便通過webservices使用這些數據。

無論如何,我預計接收JSON:

{ 
    "second": "BBB_1", 
    "third": "CCC_1", 
    "first": "AAA_1" 
}, 
{ 
    "second": "BBB_2", 
    "third": "CCC_2", 
    "first": "AAA_2" 
}, 
{ 
    "second": "BBB_3", 
    "third": "CCC_3", 
    "first": "AAA_3" 
}, 
{ 
    "second": "BBB_4", 
    "third": "CCC_4", 
    "first": "AAA_4" 
} 

但實際結果是:

{ 
    "second": "BBB_4", 
    "third": "CCC_4", 
    "first": "AAA_4" 
}, 
{ 
    "second": "BBB_4", 
    "third": "CCC_4", 
    "first": "AAA_4" 
}, 
{ 
    "second": "BBB_4", 
    "third": "CCC_4", 
    "first": "AAA_4" 
}, 
{ 
    "second": "BBB_4", 
    "third": "CCC_4", 
    "first": "AAA_4" 
} 

爲什麼以前附加價值改變他們的價值觀,以新的?

當我使用而不是列表時,我收到了相同的結果:c使用附加字典來獲得漂亮的json,而不是使用list。但結果都是一樣...... 我嘗試使用(而不是名單:C):

main_dc[i+1] = dc 

如何防止不更改列表或字典的元素的值?

+1

'dc'從哪裏來?你不斷更新不同值的同一個字典......隨着時間的推移覆蓋舊的字典。我認爲你需要在外循環的每次迭代中創建一個新的'dc'字典。 – tdelaney

回答

0

你應該追加字典的副本列表(這基本上是一個新的字典,其引用不是dc),這樣的字典進一步修改同一個對象都沒有作出之前附加:

c.append(dc.copy()) 
+0

非常感謝你,這解決了我的問題 – user2486389

0

您可以使用深copy(雖然有其他方法)。當你不使用深度和使用引用類似的對象,這會發生!這裏是你的代碼與深拷貝改變,正常工作:

import copy 
import json 
test = [(('AAA_1', 'BBB_1', 'CCC_1'), 1), (('AAA_2', 'BBB_2', 'CCC_2'), 2),(('AAA_3', 'BBB_3', 'CCC_3'), 3), (('AAA_4', 'BBB_4', 'CCC_4'), 4)] 
c = [] 
for i, j in enumerate(test): 
    dc = copy.deepcopy({}) #or simply dc = {} 
    for k, l in enumerate(j[0]): 
     if k == 0: 
      dc['first'] = l 
     elif k == 1: 
      dc['second'] = l 
     elif k == 2: 
      dc['third'] = l 
     elif k == 3: 
      dc['fourth'] = l 
    c.append(dc) 
    print "/n" 
    print "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXx" 
    print dc 
    print json.dumps(c, indent=1) 
    print c 

print json.dumps(c, indent=1) 

這裏是看的深拷貝差異和淺拷貝

In [1]: l1 = [1,2,3,4] 

In [2]: l2 = l1 

In [3]: l3 = copy.deepcopy(l1) #import copy 

In [4]: l2[0] = 0 

In [5]: l1 
Out[5]: [0, 2, 3, 4] 

In [6]: l2 
Out[6]: [0, 2, 3, 4] 

In [7]: l3 
Out[7]: [1, 2, 3, 4] 
+1

當你可以簡單地執行'dc = {}'時,你爲什麼要深刻拷貝一個空字典。即使你需要複製,'deepcopy'在這裏仍然不適用。 –

+0

你是對的;)!但我只是想讓他學習複製和參考的概念! –

+1

謝謝你的幫助和教訓! 我不知道在Python中有像deepcopy這樣的東西!這個解決方案解決了我的問題!現在我更聰明瞭,謝謝你! – user2486389

0

在你的代碼的dc定義缺少一個很好的例子,但我假設你在之前的所有循環中定義了它。這意味着您在每次迭代中都不會生成新的dc對象。相反,您可以重複使用第一個,覆蓋其內容,並將其重複附加到c。 「附加」在這裏意味着指向同一對象的四個鏈接被附加到c

您應該移動的dc定義裏面i, j循環,剛進入k, l循環之前。這會在循環的每次迭代中創建一個新對象。

... 
for i, j in enumerate(test): 
    dc = {} 
    for k, l in enumerate(j[0]): 
    ... 
+0

你的確是這樣寫的。感謝您的幫助,它解決了我的問題! – user2486389

相關問題