さまざまな長さの一連のリストを作成したいと考えています。各リストには同じ要素が含まれ、回数がe
繰り返されn
ます (ここでn
= リストの長さ)。
各リストにリスト内包表記を使用せずにリストを作成するにはどうすればよい[e for number in xrange(n)]
ですか?
さまざまな長さの一連のリストを作成したいと考えています。各リストには同じ要素が含まれ、回数がe
繰り返されn
ます (ここでn
= リストの長さ)。
各リストにリスト内包表記を使用せずにリストを作成するにはどうすればよい[e for number in xrange(n)]
ですか?
次のように書くこともできます。
[e] * n
たとえば e が空のリストの場合、 n 個の独立した空のリストではなく、同じリストへの参照が n 個あるリストが得られることに注意してください。
性能試験
一見すると、repeat が n 個の同一要素を持つリストを作成する最速の方法のように見えます。
>>> timeit.timeit('itertools.repeat(0, 10)', 'import itertools', number = 1000000)
0.37095273281943264
>>> timeit.timeit('[0] * 10', 'import itertools', number = 1000000)
0.5577236771712819
しかし、待ってください - それは公正なテストではありません...
>>> itertools.repeat(0, 10)
repeat(0, 10) # Not a list!!!
この関数itertools.repeat
は実際にリストを作成するのではなく、必要に応じてリストを作成するために使用できるオブジェクトを作成するだけです! もう一度試してみましょう。ただし、リストに変換します。
>>> timeit.timeit('list(itertools.repeat(0, 10))', 'import itertools', number = 1000000)
1.7508119747063233
リストが必要な場合は、 を使用します[e] * n
。要素を遅延生成する場合は、 を使用しますrepeat
。
>>> [5] * 4
[5, 5, 5, 5]
繰り返される項目がリストの場合は注意してください。リストは複製されません: すべての要素が同じリストを参照します!
>>> x=[5]
>>> y=[x] * 4
>>> y
[[5], [5], [5], [5]]
>>> y[0][0] = 6
>>> y
[[6], [6], [6], [6]]
Python で n 回繰り返される単一アイテムのリストを作成する
ユースケースに応じて、異なるセマンティクスで異なる手法を使用する必要があります。
None、bool、int、float、string、tuple、frozenset などの不変アイテムの場合、次のようにできます。
[e] * 4
これは通常、リスト内の不変アイテム (文字列、タプル、frozensets など) でのみ使用されることに注意してください。これらはすべて、メモリ内の同じ場所にある同じアイテムを指しているためです。すべての文字列のスキーマを使用してテーブルを作成する必要がある場合、これを頻繁に使用します。これにより、非常に冗長な 1 対 1 のマッピングを行う必要がなくなります。
schema = ['string'] * len(columns)
リストを乗算すると、同じ要素が何度も得られます。これが必要になることはめったにありません。
[iter(iterable)] * 4
これは、イテラブルをリストのリストにマップするために使用されることがあります。
>>> iterable = range(12)
>>> a_list = [iter(iterable)] * 4
>>> [[next(l) for l in a_list] for i in range(3)]
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
a_list
同じ範囲反復子が 4 回含まれていることがわかります。
>>> a_list
[<range_iterator object at 0x7fde73a5da20>, <range_iterator object at 0x7fde73a5da20>, <range_iterator object at 0x7fde73a5da20>, <range_iterator object at 0x7fde73a5da20>]
私は長い間 Python を使用してきましたが、変更可能なオブジェクトで上記を実行するユースケースはほとんど見たことがありません。
代わりに、たとえば、変更可能な空のリスト、セット、または辞書を取得するには、次のようにする必要があります。
list_of_lists = [[] for _ in columns]
アンダースコアは、このコンテキストでは単に使い捨ての変数名です。
番号だけを持っている場合、それは次のようになります。
list_of_lists = [[] for _ in range(4)]
は_
特に特別なものではありませんが、変数を使用するつもりがなく、他の名前を使用すると、コーディング環境のスタイル チェッカーがエラーを出す可能性があります。
変更可能なオブジェクトでこれを行うことに注意してください。それらの1つを変更すると、それらはすべて同じオブジェクトであるため、すべて変更されます。
foo = [[]] * 4
foo[0].append('x')
foo が返すようになりました:
[['x'], ['x'], ['x'], ['x']]
しかし、不変オブジェクトを使用すると、オブジェクトではなく参照を変更するため、機能させることができます。
>>> l = [0] * 4
>>> l[0] += 1
>>> l
[1, 0, 0, 0]
>>> l = [frozenset()] * 4
>>> l[0] |= set('abc')
>>> l
[frozenset(['a', 'c', 'b']), frozenset([]), frozenset([]), frozenset([])]
しかし繰り返しになりますが、変更可能なオブジェクトはこれには適していません。インプレース操作は参照ではなくオブジェクトを変更するからです。
l = [set()] * 4
>>> l[0] |= set('abc')
>>> l
[set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b'])]
Itertools には、そのための機能があります。
import itertools
it = itertools.repeat(e,n)
もちろんitertools
、リストの代わりにイテレータを提供します。[e] * n
はリストを提供しますが、それらのシーケンスで何をするかによっては、itertools
バリアントの方がはるかに効率的です。
[e] * n
動作するはずです