web-dev-qa-db-ja.com

Pythonリストの乗算:[[...]] * 3は、変更時に互いにミラーリングする3つのリストを作成します

なぜこれが起こっているのですか?私は本当に理解していません:

>>> P = [ [()]*3 ]*3
>>> P
[[(), (), ()], [(), (), ()], [(), (), ()]]
>>> P[0][0]=1
>>> P
[[1, (), ()], [1, (), ()], [1, (), ()]]
36
KFL

同じリストへの3つの参照を作成しました。

>>> a = b = []
>>> a.append(42)
>>> b
[42]

あなたはこれをしたいです:

P = [[()] * 3 for x in range(3)]

リストは変更可能であり、リストに数値を乗算しても、その要素はコピーされません。リスト内包表記に変更してみると、[()]*3が3回評価され、3つの異なるリストが作成されます。

P = [ [()]*3 for i in range(3) ]
8
icktoofay

次のように書くこともできます。これは、構造[[()]*3]*3を示す利点があります。

>>> P=[i[:] for i in [[()]*3]*3]
>>> P[0][0]=1
>>> P
[[1, (), ()], [(), (), ()], [(), (), ()]

また、範囲を使用するよりもわずかに高速です。 ipythonシェルから:

In [1]: timeit P = [ [()]*3 for i in range(3) ]
1000000 loops, best of 3: 1.41 us per loop

In [2]: timeit P=[i[:] for i in [[()]*3]*3]
1000000 loops, best of 3: 1.27 us per loop
6
John La Rooy

これは実際には3回複製された同じ内部リスト(同じ参照)であるため、いずれか1つを変更すると、実際にはそれらすべてが変更されます。

したがって、内部リスト[()]*3は、3つのタプルのリストを生成します。ただし、このリストは3回複製されます。ただし、Pythonでは、乗算されるのは実際には参照のリストであるため、参照は複製されますが、各参照は依然として同じ基になるリストを指します。

5
dhg