4

私はPythonで二次元ベクトルを構築していましたが、最初はすべてゼロにしたかったので、numpyを使いたくなかったので、これを試しました:

columns = 8
rows = 5
m = [[0]* (columns)] * (rows)
m[3][2] = 1
print m

そして、私は予期しない動作をしました:

>> [[0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0]]

このように二次元配列を構築すると、各行が単一の行への参照になるように見えるため、それらのいずれかに書き込むと、それらすべてに書き込むことになります。

一部の人には明らかなように聞こえるかもしれませんが、私は少し靴下を履きました. もちろん、別のアプローチを使用して修正できますが、なぜこれが起こっているのか知りたいです。

誰でも説明できますか?で単純な配列を作成すると、なぜこれが起こらないのです[0] * size_of_arrayか?

4

3 に答える 3

5

これは一般的な Python gothca です。rows内部リストを作成しているのではなくrows、同じリストへの参照を作成しています。

コードは次と同等です。

inner_list = [0] * columns
m = [inner_list] * rows

*演算子を使用せずに行を作成することをお勧めします。0( int であり、 int は不変オブジェクトであるため、列の問題には遭遇しません。)

matrix = []
for row in rows:
    matrix.append([0] * columns)
于 2013-07-03T15:55:17.657 に答える
2

[0] * size_of_arrayを複数参照するリストを作成します0。このリストに別の値を入れても、影響はありません。

お気づきのとおり[[]] * num、同じリストへの参照を何度も含むリストを作成します。このリストを変更すると、変更はすべての参照を介して表示されます。

>>> a = [0] * 10
>>> [id(i) for i in a]
[31351584L, 31351584L, 31351584L, 31351584L, 31351584L, 31351584L, 31351584L, 31351584L, 31351584L, 31351584L]
>>> 
>>> all(i is a[0] for i in a)
True

対。

>>> a = [[]] * 10
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> [id(i) for i in a]
[44072200L, 44072200L, 44072200L, 44072200L, 44072200L, 44072200L, 44072200L, 44072200L, 44072200L, 44072200L]
>>> all(i is a[0] for i in a)
True

同じ状況ですが、1 つの点が異なります。

するとa[0].append(10)、その効果はすべてのリストに表示されます。

ただしa.append([])、そうすると、他のリストとは関係のない、クリーンで新しいリストが追加されます。

>>> a = [[]] * 10
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> a.append([])
>>> a[0].append(8)
>>> a
[[8], [8], [8], [8], [8], [8], [8], [8], [8], [8], []]
>>> a[-1].append(5)
>>> a
[[8], [8], [8], [8], [8], [8], [8], [8], [8], [8], [5]]
于 2013-07-03T15:53:26.027 に答える
1

[[0] * 8] * 5 を実行すると、新しいオブジェクトへの 5 つの参照を含むリストが作成されません。最初に [0] * 8 オブジェクト (リスト) を作成し、次に * 5 によって作成された各要素にその単一のリストへの参照を割り当てます。

それは以下と同等です:

a = [ 0 ] * 8
b = [ a ] * 5
于 2013-07-03T15:55:42.547 に答える