なぜこれが起こっているのですか?私は本当に理解していません:
>>> P = [ [()]*3 ]*3
>>> P
[[(), (), ()], [(), (), ()], [(), (), ()]]
>>> P[0][0]=1
>>> P
[[1, (), ()], [1, (), ()], [1, (), ()]]
同じリストへの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) ]
次のように書くこともできます。これは、構造[[()]*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
これは実際には3回複製された同じ内部リスト(同じ参照)であるため、いずれか1つを変更すると、実際にはそれらすべてが変更されます。
したがって、内部リスト[()]*3
は、3つのタプルのリストを生成します。ただし、このリストは3回複製されます。ただし、Pythonでは、乗算されるのは実際には参照のリストであるため、参照は複製されますが、各参照は依然として同じ基になるリストを指します。