2017-03-22 31 views
1

グローバル変数にリストを追加するはずのpythonプログラムがありますが、追加する代わりにリストを上書きしています。これと同じように動作し、私が作ったデモ機能:Appendがリスト内の既存のデータを上書きしています

var_gobal = [] 

def parse(list_parse,stack): 
    for element in list_parse: 
     stack.append(element["a"]) 
     print(stack) 
     global var_gobal 
     var_gobal.append(stack) 

to_parse = [{"a":"abc","b":"bcd","c":"cde"},{"a":"def","b":"efg","c":"ghi"}] 
parse(to_parse,[]) 
print (var_gobal) 

予想される出力は

[['abc'], ['abc', 'def']] 

する必要がありますしかし、その代わりに、私は

[['abc', 'def'], ['abc', 'def']] 

を取得し、リストの最初の要素はあります上書きされます。なぜこうなった?

+0

は 'グローバルvar_global'は、ループの外ではないでしょうか? – Petar

+0

同じ出力は違いはありません。 –

答えて

2

あなたは、リストのappendメソッドの代わりにスライスstack = stack[:] + [element["a"]]を使用することができます。

var_gobal = [] 

def parse(list_parse,stack): 
    global var_gobal 

    for element in list_parse: 
     stack = stack[:] + [element["a"]] 
     print(stack) 
     var_gobal.append(stack) 

to_parse = [{"a":"abc","b":"bcd","c":"cde"},{"a":"def","b":"efg","c":"ghi"}] 
parse(to_parse,[]) 
print (var_gobal) 

出力:

['abc'] 
['abc', 'def'] 
[['abc'], ['abc', 'def']] 

あるいは、同じ結果を与えるだろうstack = stack + [element["a"]]を使用して 同じように。違いを確認するには

、我々は次の例を見ることができます:

my_list = ['a', 'b'] 
tmp = [] 
global_var = [] 

for i in my_list: 
    tmp.append(i) 
    global_var.append(tmp) 

global_var 

これは[['a', 'b'], ['a', 'b']]としてglobal_var出力します。 tmpmy_listを通して反復ごとにglobal_varに追加され、が

は、すべてのすべてのtmpに(又はを指しているものをすべて)参照が変更された追加します。 sliceまたは+が使用されている場合[:]を使用しているので、代わりに、新しいリストが最初のすべての要素を使用して作成されます

my_list = ['a', 'b'] 
tmp = [] 
global_var = [] 

for i in my_list: 
    tmp = tmp[:] + [i] 
    global_var.append(tmp) 

global_var 

この結果:[['a'], ['a', 'b']]

+0

これは動作しますが、なぜ 'stack.append()'が問題を引き起こしていますか? –

+1

上記の場合と同様に、最初にスタックには '['abc']'が付加され、 'global_var'にも追加されます。しかし、次の反復では、同じスタックに 'def'が付加され、' ['abc'、 'def'] 'になります。この更新された 'stack'を追加すると、' stack'のすべての場所は同じ更新値を持ちます(配列は参照によって渡されます、ここではスタックは単に配列またはリストです)。 。 – 0p3n5ourcE

+1

ああ、今私は理解しています。ありがとう。 –

2

スタックを参照を追加する代わりにvar_globalにコピーする必要があります。

var_gobal.append(stack.copy()) 
+0

これは 'AttributeError: 'list'オブジェクトに属性 'コピー'がないというエラーを返します。 –

+0

@PrateekGupta #Patrikあなたは正しいですが、' var_gobal.append(copy(stack)) ' – stovfl

+0

@PrateekGupta'リストを書く必要があります。コピー()はpython3.3から利用可能です –

2

stack will have 2 element after second, that was saved in stack list.

var_gobal = [] 

def parse(list_parse,stack): 
    for element in list_parse: 
     stack.append(element["a"]) 
     print(stack) 
     new_stack = list(stack) 
     var_gobal.append(new_stack) 


to_parse = [{"a":"abc","b":"bcd","c":"cde"},{"a":"def","b":"efg","c":"ghi"}] 
parse(to_parse,[]) 
print (var_gobal) 

>>> print (var_gobal) 
[['abc'], ['abc', 'def']] 
+0

これは@ open-sourceの答えと一緒に働いていますが、なぜ別のリストを作成する必要がありますか?スタック変数はすでにリストであり、最初に1つの要素があり、その後に2つの要素がループした後、グローバル変数にそれを毎回追加するのはなぜですか? –

+0

その時点でスタックのコピーを作成します。スタックが変更されても、スタックのコピーには以前のスタック値が含まれます。その理由は、コメントで@ open-sourceによって提供されるからです。 –

+0

その時点でスタックのコピーを作成します。スタックが変更されても、スタックのコピーには以前のスタック値が含まれます。それは理由が@ open-sourceのコメントで提供されているからです –

関連する問題