2016-11-20 6 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に変換して、このデータをWebサービスで簡単に使用できるようにしました。

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

しかし、実際の結果は以下のとおりです:

はとにかく、私はJSONを受けることが予想

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

以前に追加の値を新しいものにそれらの値を変更するのはなぜ?

list:cの追加辞書の代わりに私が使用したときと同じ結果が得られました。これはlistを使用するよりもきれいなjsonを得るためです。しかし、結果は同じであった... は、私は(リストの代わりに:C):使用してみました

main_dc[i+1] = dc 

は、どのように私はリストや辞書の要素の値を変更しないように防ぐことができますか?

+1

'dcはどこから来たのですか?異なる値で同じ辞書を更新し続けます...古いものを上書きします。私は外側のループの各反復で新しいdc dictを作成する必要があると思います。 – 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) 

dcの定義が不足しているあなたのコードではディープコピーの違いと浅いコピー

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しますか?コピーする必要がある場合でも、ここでは「deepcopy」はまだ適用されません。 –

+0

あなたは正しいです;)!しかし、私はちょうど彼がコピーと参照の概念を学ぶことを望んでいました! –

+1

あなたの助けと授業をありがとう! pythonにdeepcopyのようなものがあることはわかりませんでした。この解決策は私の問題を解決する!今私はあなたのおかげでよりスマートです! – user2486389

0

を見るための良い例です、私はあなたがそれを定義すると仮定しますの前にすべてのループ。これは、各反復で新しいdcオブジェクトを生成しないことを意味します。代わりに、最初のものを再利用し、その内容を上書きして、それを何度も繰り返してcに追加します。 「追加」は、cに同じオブジェクトへの4つのリンクが追加されていることを意味します。

あなただけk, lループに入る前に、内i, jループをdcの定義を移動する必要があります。これはループの各反復で新しいオブジェクトを作成します。

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

あなたの書き方はまさにありました。助けてくれてありがとう、それは私の問題を解決する! – user2486389

関連する問題