web-dev-qa-db-ja.com

単一の値を変更しようとすると、2Dリストの動作がおかしい

可能性のある重複:
Pythonリストのリスト)の予期しない機能

したがって、私はPython=に比較的慣れていないため、2Dリストの操作に問題があります。

これが私のコードです:

data = [[None]*5]*5
data[0][0] = 'Cell A1'
print data

そしてここに出力があります(読みやすいようにフォーマットされています):

[['Cell A1', None, None, None, None],
 ['Cell A1', None, None, None, None],
 ['Cell A1', None, None, None, None],
 ['Cell A1', None, None, None, None],
 ['Cell A1', None, None, None, None]]

なぜすべての行に値が割り当てられるのですか?

54
Brian

これはsameリストへの5つの参照を持つリストを作成します。

data = [[None]*5]*5

代わりに次のようなものを使用して、5つの個別のリストを作成します。

>>> data = [[None]*5 for _ in range(5)]

今、それはあなたが期待することをします:

>>> data[0][0] = 'Cell A1'
>>> print data
[['Cell A1', None, None, None, None],
 [None, None, None, None, None],
 [None, None, None, None, None],
 [None, None, None, None, None],
 [None, None, None, None, None]]
68
Mark Byers

リストを含む シーケンスタイプのPythonライブラリリファレンス のように、

コピーが浅いことにも注意してください。ネストされた構造はコピーされません。これはしばしば新しいPython=プログラマーを悩ませます;考慮してください:

>>> lists = [[]] * 3
>>> lists
  [[], [], []]
>>> lists[0].append(3)
>>> lists
  [[3], [3], [3]]

[[]]は空のリストを含む1要素のリストであるため、[[]] * 3の3つの要素はすべてこの1つの空のリスト(へのポインタ)です。リストの要素を変更すると、この単一のリストが変更されます。

このようにして、さまざまなリストのリストを作成できます。

>>> lists = [[] for i in range(3)]  
>>> lists[0].append(3)
>>> lists[1].append(5)
>>> lists[2].append(7)
>>> lists
  [[3], [5], [7]]
14
Mark

pythonでは、すべての変数がオブジェクトなので、参照です。最初に5つのNonesの配列を作成し、次に同じオブジェクトの5倍の配列を作成します。

2
lfagundes