4

私はこの問題に頭を悩ませてきました。リストを作成して 4 つのコピーを作成します。そのうちの 1 つだけが同じメモリ インデックスを共有します。元のリストを変更すると、それらのコピーのうち 3 つも何らかの形で変更され、そのうちの 2 つのメモリ インデックスは異なります。オリジナルと同じコマンドを使用してリストを作成する場合にのみ、オリジナルへの変更の影響を受けないリストを作成できます。これはどのように可能ですか?コンソールからの出力は次のとおりです。

>>> orig=[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 123, 0]]
>>> id(orig)
151498220
>>> copy1=orig   #same index
>>> id(copy1)
151498220
>>> copy2=orig[:]   #different index
>>> id(copy2)
151498348
>>> copy3=list(orig)   #different index
>>> id(copy3)
151503020
>>> copy4=[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 123, 0]]
>>> id(copy4)
151498636
>>> orig[0][1]=34
>>> copy1
[[0, 34, 0, 0], [0, 0, 0, 0], [0, 0, 123, 0]]   #expected, same memory index
>>> copy2
[[0, 34, 0, 0], [0, 0, 0, 0], [0, 0, 123, 0]]   #WTF?!?!?
>>> copy3
[[0, 34, 0, 0], [0, 0, 0, 0], [0, 0, 123, 0]]   #ARGH!!!
>>> copy4
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 123, 0]]   #workaround?
>>> id(orig)
151498220
>>> id(copy1)
151498220
>>> id(copy2)
151498348
>>> id(copy3)
151503020
>>> id(copy4)
151498636

メモリ インデックスは変更されませんでしたが、リストは変更されました。メモリ インデックスが orig と同じであるため、copy1 のみが変更されているはずです。

4

3 に答える 3

10

これは、浅いコピーを作成しているだけだからです。代わりにディープ コピーを作成する必要があります。

コピーモジュールのドキュメントに従って:

  • 浅いコピーは、新しい複合オブジェクトを構築し、(可能な範囲で) オリジナルで見つかったオブジェクトへの参照を挿入します。
  • ディープ コピーは、新しい複合オブジェクトを構築し、再帰的に、元のオブジェクトで見つかったオブジェクトのコピーを挿入します。

内部リストの id を比較することで確認できます。

>>> orig=[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 123, 0]]
>>> id(orig)
151498220
>>> copy2=orig[:]   #different index
>>> id(copy2)
151498348

>>> id(copy2[0]) == id(orig[0])  # inner list have same id
True

deepcopy次を使用して作成できますcopy.deepcopy(x)

>>> import copy
>>> 
>>> copy3 = copy.deepcopy(orig)
>>> 
>>> id(copy3[0]) == id(orig[0])   # inner list have different id
False

>>> orig[0][3] = 34
>>> 
>>> orig
[[0, 34, 0, 0], [0, 0, 0, 0], [0, 0, 123, 0]]
>>> copy3
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 123, 0]]
于 2013-07-17T18:46:27.783 に答える
0

あなたのリストは名前のリストであり、あなたが考えているリストのリストではありません。リストした方法のいずれかを使用してリストのコピーを作成すると (スライス、古いリストに基づいて新しいリストを作成するなど)、新しい外部リストを作成しますが、新しいリストの名前は同じ内部リストを参照します。古いものの名前。

# One through three are all examples of:

first_list, second_list, third_list = [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 123, 0]
original = [first_list, second_list, third_list]
another_list = original[:]

# We do indeed have another list
assert id(original) != id(another_list)

# But the *references* in the list are pointing at the same underlying child list
assert id(original[0]) == id(another_list[0])
于 2013-07-17T18:46:05.487 に答える