6

これは非常に単純なプログラムです。

 a = [[]]*3

 print str(a)

 a[0].append(1)
 a[1].append(2)
 a[2].append(3)

 print str(a[0])
 print str(a[1])
 print str(a[2])

これが私が期待していた出力です:

 [[], [], []]
 [1]
 [2]
 [3]

しかし、代わりに私はこれを手に入れます:

 [[], [], []]
 [1, 2, 3]
 [1, 2, 3]
 [1, 2, 3]

私がここで得られないものが本当にあります!

4

5 に答える 5

12

あなたがしなければならない

a = [[] for i in xrange(3)]

いいえ

a = [[]]*3

今それは動作します:

$ cat /tmp/3.py
a = [[] for i in xrange(3)]

print str(a)

a[0].append(1)
a[1].append(2)
a[2].append(3)

print str(a[0])
print str(a[1])
print str(a[2])

$ python /tmp/3.py
[[], [], []]
[1]
[2]
[3]

あなたが同じようなことをするとき、あなたはリストの中でa = [[]]*3同じリストを[]3回得る。同じことは、それらの1つを変更すると、すべてを変更することを意味します(3回参照されるリストは1つしかないため)。

この問題を回避するには、3つの独立したリストを作成する必要があります。そして、あなたはリスト内包でそれをします。ここで、独立した空のリストで構成されるリストを作成します[]。反復ごとに新しい空のリストが作成されます(この場合、とxrange(3)の違いはそれほど重要ではありませんが、数値の完全なリストを生成せず、代わりにイテレータオブジェクトを返すため、少し優れています)。rangexrangexrange

于 2012-06-27T05:31:19.500 に答える
5

あなたが書くとき:

a = [[]]*3

内部の空のリストのコピーを3つ作成するのではなく、同じオブジェクトへの参照を3つ作成します。

同じように、次の場合:

b = [1,2,3]
c = b
c.append(4)
print b

出力として次のようになります。

[1, 2, 3, 4]

これは、bとcが同じリストへの2つの異なる参照(2つの異なる名前を言う場合があります)であるためです。オブジェクトはどの参照からでも変更できますが、同じものを指しているため、すべての参照の結果が表示されます。

于 2012-06-27T05:33:32.827 に答える
5

このアプローチの基本的な問題は、リストに3を掛けると、結果のリストに同じリストが3つ含まれることです。したがって、、、a[0]およびa[1]すべてa[2]が同じものを参照します。これらのいずれかに追加すると、同じリストに追加されます。これが、append()通話の効果が3倍になっているように見える理由です。

代わりに、同じリストを参照せずにリストのリストを生成します。例として、次のようにリスト内包表記を使用できます。

[[] for i in range(3)]
于 2012-06-27T05:34:41.420 に答える
2

これにより、明確なアイデアが得られます。すべてのオブジェクトは同じid()を持ち、すべてが可変であるため、いずれか1つを編集すると、他のオブジェクトも自動的に編集されます。これらはすべて、id=18671936の同じオブジェクトへの参照にすぎないためです。 mはすべて異なるid()を持っているため、それらはすべて異なるオブジェクトです。

>>> l = [[]]*4
>>> for x in l:
        print(id(x))

18671936 
18671936
18671936
18671936

>>> m=[[],[],[],[]]
>>> for x in m:
        print(id(x))

10022256
18671256
18672496
18631696

したがって、次のようにリストを作成する必要があります。

>>> a=[[] for _ in range(4)]
>>> a[0].append(1)
>>> a[2].append(5)
>>> a
[[1], [], [5], []]
于 2012-06-27T06:03:30.580 に答える
1

私がここで得られないものが本当にあります!

a = [[]]*3ここでの問題は、配列と辞書が参照として保存されるため、リストを同じ参照に設定していることです。

>>> a = [[]]*3
>>> a[0] is a[1] or a[0] is a[2]
True
>>> a[0] is a[1] or a[0] is a[2] or a[1] is a[2]
True
>>> 

a = [{}]*3`を実行しても同じことが起こります

そのため、注意する必要があります。リスト内包表記を実行するか、[[] for _ in xrange(3)]3つの配列すべてを静的に定義することができます[[], [], []]

>>> a = [[] for _ in xrange(3)]
>>> a[0] is a[1] or a[0] is a[2] or a[1] is a[2]
False
>>> 
于 2012-06-27T05:39:43.490 に答える