1

リストを定義して、次のように1つのアイテムを変更しようとすると:

list_of_lists = [['a', 'a', 'a'], ['a', 'a', 'a'], ['a', 'a', 'a']]
list_of_lists[1][1] = 'b'
for row in list_of_lists:
    print row

意図したとおりに動作します。しかし、リスト内包表記を使用してリストを作成しようとすると、次のようになります。

row = ['a' for range in xrange(3)]
list_of_lists = [row for range in xrange(3)]
list_of_lists[1][1] = 'b'
for row in list_of_lists:
    print row

その結果、リスト内のアイテムの列全体が変更されます。どうしてこれなの?リスト内包表記で目的の効果を達成するにはどうすればよいですか?

4

3 に答える 3

5

これを行う場合について考えてみましょう:

>>> row = ['a' for range in xrange(3)]
>>> row2 = row
>>> row2[0] = 'b'
>>> row
['b', 'a', 'a']

これは、 と が同じリストの 2 つの異なる名前であるためrow発生しrow2ます( があります)。ネストされたリストを使用した例では、これが少しわかりにくいだけです。row is row2

それらを異なるリストにするために、変数の代入を行う代わりに毎回リスト作成コードを再実行させることができます:

list_of_lists = [['a' for range in xrange(3)] for _ in xrange(3)]

または、完全な古いリストの一部を使用して、毎回新しいリストを作成します。

list_of_lists = [row[:] for range in xrange(3)]

これはすべてのシーケンスで一般的に機能するとは限りませんが、リストのスライスによってスライスの新しいリストが作成されることがあります。これは、たとえば、numpy 配列では発生しません。これらのスライスは、コピーではなく、配列の一部のビューです。リストだけでなく、より一般的に作業する必要がある場合は、次のcopyモジュールを使用します。

from copy import copy
list_of_lists = [copy(row) for range in xrange(3)]

また、これは変数の名前としては最適ではないことに注意してください。rangeこれは、ビルトインを隠しているためです。このような使い捨ての名前_はかなり一般的です。

于 2012-09-17T03:35:23.707 に答える
2

これは、Python のほとんどのオブジェクト (文字列と数値を除く) が参照を渡されるために発生します (正確には参照ではありませんが、ここではより良い説明があります)。同じリスト(「行」と呼ばれるもの)への3つの参照のうち。したがって、1 つの行の値を変更すると、すべての行でその変更が表示されます)。

したがって、「マトリックス」の作成を次のように変更する必要があります。

list_of_lists = [list(row) for range in xrange(3)]

ここでは、リストのコピーを正しく取得する方法についていくつかのアイデアを示します。何をしようとしているかに応じて、どちらかを使用できます...

それが役に立てば幸い!

于 2012-09-17T03:38:24.033 に答える
0

参照だけでなく、リストをコピーします。

list_of_lists = [row[:] for range in xrange(3)]
于 2012-09-17T03:24:51.900 に答える