10

リスト拡張の​​意図された動作について何かが足りないかもしれませんが、なぜ次のことが起こるのですか?

x = [[],[]]
y = [[]] * 2

print x       # [[],[]]
print y       # [[],[]]
print x == y  # True

x[0].extend([1])
y[0].extend([1])

print x    # [[1],[]], which is what I'd expect
print y    # [[1],[1]], wtf?

*正確にはわかりませんが、ここではオペレーターが予期しないことをしていると思います。==オペレーターとrepr両方が同じように見せても、元のxとy(extendを呼び出す前)が実際には等しくないようにする何かが内部で起こっているようです。

これに出くわしたのは、実行時に決定されたサイズの空のリストのリストを事前に入力したかったのですが、それが想像どおりに機能していないことに気づきました。同じことをするためのより良い方法を見つけることができますが、なぜこれがうまくいかなかったのか興味があります。これはPython2.5.2です。ところで-私は新しいバージョンをインストールしていないので、これがバグである場合、それがすでに修正されているかどうかはわかりません。

4

3 に答える 3

17

の場合[something] * 2、python は単に参照コピーを作成しています。したがって、囲まれた型が変更可能な場合、それらを変更すると、アイテムが参照されているすべての場所に反映されます。

あなたの例では、同じ囲まれたリストオブジェクトy[0]を指しています。これは、または を交互y[1]に実行することで確認できます。y[0] is y[1]id(y[0]) == id(y[1])

ただし、リスト要素を再割り当てすることはできます。

y[0] = [1]

最初の要素を要素「1」を含む新しいリストに再バインドすると、期待どおりの結果が得られます。

Python ストア参照のコンテナーであり、ほとんどのシーケンス コンテナーで同じ項目を複数回参照することが可能です。リストは実際にはそれ自体を要素として参照できますが、これの有用性は限られています。

不変型を含むリストを乗算した場合、この問題は発生しませんでした。

a = [0, 1] * 2

上記はリスト[0, 1, 0, 1]を提供し、実際には両方のインスタンスが同じオブジェクトを指していますが、それらは不変であるため、 「1」を含むオブジェクト1の値を変更することはできず、要素を再割り当てするだけです。int

そうすること:a[1] = 5 としてa表示され[0, 5, 0, 1]ます。

于 2010-02-16T21:21:22.760 に答える
4

このステートメントは、同じリストの 2 つのコピーを含むリストy = [[]] * 2にバインドします。y使用する:

y = [[], []]

また

y = [[] for n in range(2)]
于 2010-02-16T21:20:19.937 に答える
1

y1 つの変更可能なリストへの 2 つの参照が含まれています。

于 2010-02-16T21:20:42.777 に答える