N回繰り返された単一アイテムのリストを作成する


523

さまざまな長さの一連のリストを作成したい。各リストには、同じ要素eが繰り返されnます(ここでn=リストの長さ)。

リスト[e for number in xrange(n)]ごとに内包表記を使用せずにリストを作成するにはどうすればよいですか?

回答:


778

次のように書くこともできます:

[e] * n

eがたとえば空のリストである場合、n個の独立した空のリストではなく、同じリストへのn個の参照を持つリストを取得することに注意してください。

性能試験

一見する、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


23
同じ要素を持つリストを作成するパフォーマンスがPythonプログラムのパフォーマンスの重要なコンポーネントになることはほとんどありません。
Arthur

11
上記のように、eが空のリストの[[]] * n場合、予期しない結果が生じる可能性があります。作成するにはユニークな空のサブリストを、するために、理解使用:[[] for i in range(0,n)]
ジョサイアYoderの

149
>>> [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]]

80

Pythonでn回繰り返された単一アイテムのリストを作成する

不変アイテム

None、bools、ints、floats、strings、tuples、frozensetsなどの不変アイテムの場合、次のように実行できます。

[e] * 4

これらはすべてメモリ内の同じ場所にある同じ項目を指すため、リスト内の不変の項目(文字列、タプル、frozensetsなど)でのみ使用するのが最適であることに注意してください。すべての文字列のスキーマを含むテーブルを作成する必要がある場合、これを頻繁に使用するため、非常に冗長な1対1のマッピングを指定する必要がありません。

schema = ['string'] * len(columns)

変更可能なアイテム

私は長い間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'])]

26

Itertoolsにはそのための機能があります。

import itertools
it = itertools.repeat(e,n)

もちろんitertools、リストの代わりにイテレータを提供します。[e] * nリストが表示されますが、これらのシーケンスで何を行うかによっては、itertoolsバリアントの方がはるかに効率的です。


13

他の人が指摘したように、可変オブジェクトに*演算子を使用すると参照が重複するため、1つを変更するとすべてが変更されます。可変オブジェクトの独立したインスタンスを作成する場合、xrange構文がこれを行う最もPythonicな方法です。決して使用されない名前付き変数に悩まされている場合は、匿名のアンダースコア変数を使用できます。

[e for _ in xrange(n)]

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.