list.append()
はリストの最後に追加するための明らかな選択です。これは 合理的な説明 がないlist.prepend()
のためのものです。私のリストが短く、パフォーマンスへの懸念が無視できると仮定すると、
list.insert(0, x)
または
list[0:0] = [x]
慣用句?
s.insert(0, x)
形式が最も一般的です。
あなたがそれを見るときはいつでも、それはリストの代わりに collections.deque を使うことを考慮するべき時かもしれません。
あなたが機能的な方法で行くことができるならば、以下はかなり明らかです
new_list = [x] + your_list
もちろん、x
をyour_list
に挿入していないのではなく、x
があらかじめ追加された新しいリストを作成しました。
短いPythonリストの前に付ける慣用的な構文は何ですか?
通常、Pythonのリストの先頭に繰り返し追加したくはありません。
それが short であり、あなたがそれをあまりしていないのであれば...それから大丈夫です。
list.insert
list.insert
はこのように使用できます。
list.insert(0, x)
しかし、これは非効率的です。Pythonではlist
はポインタの配列なので、Pythonはリスト内のすべてのポインタを1つ下に移動して最初のスロットにオブジェクトへのポインタを挿入する必要があるためですあなたが尋ねるように、かなり短いリストのために効率的です。
要素を追加するのに効率的なコンテナが必要な場合は、二重リンクリストが必要です。 Pythonには1つあります - それはdeque
と呼ばれます。
deque.appendleft
collections.deque
にはリストの多くのメソッドがあります。 list.sort
は例外で、deque
をlist
の代わりにLiskovを完全に代用することはできません。
>>> set(dir(list)) - set(dir(deque))
{'sort'}
deque
には(appendleft
と同様に)popleft
メソッドもあります。 deque
は両端キューと二重リンクリストです - 長さに関係なく、何かを前処理するのに常に同じ時間がかかります。大きなO記法では、リストのO(1)時間に対するO(n)時間。使い方は次のとおりです。
>>> import collections
>>> d = collections.deque('1234')
>>> d
deque(['1', '2', '3', '4'])
>>> d.appendleft('0')
>>> d
deque(['0', '1', '2', '3', '4'])
deque.extendleft
繰り返しに追加されるdequeのextendleft
メソッドも関連があります。
>>> from collections import deque
>>> d2 = deque('def')
>>> d2.extendleft('cba')
>>> d2
deque(['a', 'b', 'c', 'd', 'e', 'f'])
各要素は一度に一つずつ追加されるので、順番を逆にすることに注意してください。
list
対deque
のパフォーマンス最初にいくつかの反復的な前置きで設定します。
import timeit
from collections import deque
def list_insert_0():
l = []
for i in range(20):
l.insert(0, i)
def list_slice_insert():
l = []
for i in range(20):
l[:0] = [i] # semantically same as list.insert(0, i)
def list_add():
l = []
for i in range(20):
l = [i] + l # caveat: new list each time
def deque_appendleft():
d = deque()
for i in range(20):
d.appendleft(i) # semantically same as list.insert(0, i)
def deque_extendleft():
d = deque()
d.extendleft(range(20)) # semantically same as deque_appendleft above
とパフォーマンス:
>>> min(timeit.repeat(list_insert_0))
2.8267281929729506
>>> min(timeit.repeat(list_slice_insert))
2.5210217320127413
>>> min(timeit.repeat(list_add))
2.0641671380144544
>>> min(timeit.repeat(deque_appendleft))
1.5863927800091915
>>> min(timeit.repeat(deque_extendleft))
0.5352169770048931
デキューははるかに高速です。リストが長くなるにつれて、dequeのパフォーマンスがさらに向上することが期待されます。もしあなたがdequeのextendleft
を使うことができれば、おそらくそのようにして最高のパフォーマンスを得るでしょう。
誰かが私のようにこの質問を見つけたならば、提案された方法の私のパフォーマンステストはここにあります:
Python 2.7.8
In [1]: %timeit ([1]*1000000).insert(0, 0)
100 loops, best of 3: 4.62 ms per loop
In [2]: %timeit ([1]*1000000)[0:0] = [0]
100 loops, best of 3: 4.55 ms per loop
In [3]: %timeit [0] + [1]*1000000
100 loops, best of 3: 8.04 ms per loop
ご覧のとおり、insert
とスライスの割り当ては明示的な加算よりもほぼ2倍高速で、結果は非常によく似ています。 Raymond Hettinger が述べたようにinsert
はより一般的な選択肢であり、私は個人的にはリストの先頭にこの方法を付けるのを好みます。
最初のものは確かにはるかに明確で意図をはるかに良く表しています:あなたはリスト全体ではなく単一の要素を挿入したいだけです。