ネストされたリストを作成するときに今日問題が発生し、その背後に誰がいるかを確認することにしました
>>> board1 = [[0]*3 for _ in range(3)]
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> board2 = [[0]*3]*3
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
はい、どちらの方法でもネストされたリストを作成できるようですが、値を割り当てるときに問題があります
>>> board1[1][1] = 1
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]
>>> board2[1][1] = 1
[[0, 1, 0], [0, 1, 0], [0, 1, 0]]
情報を確認し、これがboard2リストの3つの参照が同じオブジェクトを参照する理由であることを確認します。まだ困惑している新人として、次の例をもう一度見ました
>>> board3 = []
>>> for i in range(3):
... row=[0] * 3
... board3.append(row)
...
>>> board3
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> board3[1][1] = 1
>>> board3
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]
board3とboard1は同じで、反復ごとに新しいリストが作成されます。つまり、リストの各行が異なるアドレスを指します。
以下の例を見てください
>>> board4 = []
>>> row=[0] * 3
>>> for i in range(3):
... board4.append(row)
>>> board4
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> board4[1][1] = 1
>>> board4
[[0, 1, 0], [0, 1, 0], [0, 1, 0]]
board4とboard2は同じで、反復ごとに同じオブジェクトがリストに追加されます。つまり、リストの各行は同じブロックアドレスを指します。
なぜこれが起こっているのですか?
これが原則であり、参照と可変オブジェクトの背後にある罠です。
デフォルトがあれば、Pythonの浅いコピーを行うことですlist1
リストlist(list1
)またはlist1[:]
作成list1
コピーを、彼らは(コピー、コンテナの唯一の最も外側の層、要素のコピーがまだコンテナ内のソース要素を参照してください)シャローコピーを行います。同じリストオブジェクトを共有する浅いコピー
それらがどのように動作するかを明確に理解するために、ネストされたリストを作成するプロセスを以下に視覚化します
board1 = [[0]*3 for _ in range(3)]
board1[1][1] = 1
board2 = [[0]*3]*3
board2[1][1] = 1
最初の行:
最初に反復可能なオブジェクトを作成し、ループ本体で作成し[0]*3
、新しいリストの対応する位置に値を割り当てます
あなたが見ることができ、各サブリストは、ネストされたリスト内の別々のスペースを占有し、その割り当てはboard1[1][1] = 1
一つだけを変更します
3行目:
ネストされたリストの3つのサブリストは同じオブジェクトを指しているため、割り当て操作によって最初に見た状況が発生します。
私たちは、にすることができ、ここでする可視化プロセスの実行を確認するために自分のコードを入力してみてください。ウェルカムメッセージ