2012-01-07 2 views
5

私はここで最後の2時間を費やしています。私の問題は、関数内で行われた変更によって影響を受けるパラメータ/引数の共通の問題です。たとえ関数内でvariable_cloned = variable[:]を使用して参照/エイリアスを削除しても、参照なしで内容をコピーすることができます。ここで関数内の渡された引数/パラメータは、参照/エイリアスを削除した後でも変更されています。

は、コードは次のとおりです。私は気づい何

def add_column(m):  
    #this should "clone" m without passing any reference on  
    m_cloned = m[:] 
    for index, element in enumerate(m_cloned): 
     # parameter m can be seen changing along with m_cloned even 
     # though 'm' is not touched during this function except to 
     # pass it's contents onto 'm_cloned'   
     print "This is parameter 'm' during the for loop...", m 
     m_cloned[index] += [0] 
    print "This is parameter 'm' at end of for loop...", m  
    print "This is variable 'm_cloned' at end of for loop...", m_cloned 
    print "m_cloned is m =", m_cloned is m, "implies there is no reference" 
    return m_cloned 

matrix = [[3, 2], [5, 1], [4, 7]] 
print "\n" 
print "Variable 'matrix' before function:", matrix 
print "\n" 
add_column(matrix) 
print "\n" 
print "Variable 'matrix' after function:", matrix 

はm_clonedの別名であるかのように関数内のパラメーター「m」が変化しているということです - 限り私は私が持って言うことができるようにしかし、関数の最初の行でエイリアスを削除しました。どこにいても、私はオンラインで見てきましたが、この行はパラメータへの参照がないことを確認するように思われますが、動作しません。

私は単純な間違いをしているに違いないと確信していますが、2時間後には私はそれを見つけるつもりはないと思います。

+1

"...私はvariable_cloned =を使ってリファレンス/エイリアスを削除しましたが、変数[:]を参照せずに内容をコピーする関数内の "これにより 'variable_cloned'は' variable'とは別のリストを参照しますが、2つのリストは同じ内容を含みます:あなたの3つの(2項目)リストへの参照。 –

答えて

9

あなたはdeepcopyを必要とするようですが、代わりに[:]はあなたに与えるものであるシャローコピー、の、になります。

from copy import deepcopy 
list2 = deepcopy(list1) 

は、ここでのコピーの2種類を比較長い例です:

from copy import deepcopy 

list1 = [[1], [1]] 
list2 = list1[:] # while id(list1) != id(list2), it's items have the same id()s 
list3 = deepcopy(list1) 

list1[0] += [3] 

print list1 
print list2 
print list3 

出力:

[[1, 3], [1]] # list1 
[[1, 3], [1]] # list2 
[[1], [1]]  # list3 - unaffected by reference-madness 
+0

うわー、ありがとうございました。私は[リンク](http://docs.python.org/library/copy.html)を見ていますが、これは深いコピーと浅いコピーの違いを幾分説明していますが、実際にはどういう意味なのかよく分かりません。変数を関数に渡すたびにディープコピーを行いますか? – FiveAlive

+1

@FiveAlive必ずしもそうではありません。場合によっては、「子」オブジェクトへの参照を保持したいことがあります。 string/intのようなものは値を変更することはできませんが、代わりにあなたのケースでは問題にならない新しいコピーに置き換えられますので、時には問題ではありません(不変の "子"を扱う場合)。 「知っている」とは戦闘の半分(彼らは言う)だから、あなたが知っているので、次回はあなたが必要とするものにもっと注意を払うと確信しています。 –

+0

もう一度、ありがとうございました。 – FiveAlive

関連する問題