list.append()
是添加到列表末尾的明显选择。这是丢失的list.prepend()
的{{3}}。假设我的列表很短并且性能问题可以忽略不计,那么
list.insert(0, x)
或
list[0:0] = [x]
惯用?
答案 0 :(得分:652)
s.insert(0, x)
表格是最常见的。
无论何时看到它,都可以考虑使用collections.deque代替列表。
答案 1 :(得分:218)
如果你可以采用功能方式,以下内容非常清楚
new_list = [x] + your_list
当然,您尚未将x
插入your_list
,而是已创建了一个新的列表x
已预先准备好。
答案 2 :(得分:66)
前缀为短python列表的惯用语法是什么?
您通常不希望重复使用Python中的列表。
如果它是 短 ,而你没有做太多......那就好了。
list.insert
list.insert
可以这种方式使用。
list.insert(0, x)
但是效率很低,因为在Python中,list
是一个指针数组,Python现在必须将列表中的每个指针都向下移动一个,以便在第一个指针中插入指针。插槽,所以这对于相当短的列表来说真的很有效,就像你问的那样。
如果你想要一个能够在前置元素上有效的容器,你需要一个双向链表。 Python有一个 - 它被称为deque
。
deque.appendleft
collections.deque
有许多列表方法。 list.sort
是一个例外,使deque
明确地不完全Liskov可替代list
。
>>> 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
,那么你可能会获得最好的表现。
答案 3 :(得分:55)
如果有人发现像我这样的问题,这是我对提议方法的性能测试:
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
和切片分配几乎是显式添加的两倍,并且结果非常接近。由于Raymond Hettinger注意到insert
是更常见的选项,我个人更喜欢这种方式来预先列出。
答案 4 :(得分:4)
第一个肯定更清晰,更好地表达了意图:你只想插入一个元素,而不是整个列表。
答案 5 :(得分:1)
我认为,在Python中,将元素或列表添加到另一个列表的最优雅,最惯用的方式是使用扩展运算符*(也称为解包运算符),
# Initial list
l = [4, 5, 6]
# Modification
l = [1, 2, 3, *l]
修改后的结果列表为[1, 2, 3, 4, 5, 6]
我还喜欢简单地将两个列表与运算符+组合在一起,如图所示,
# Prepends [1, 2, 3] to l
l = [1, 2, 3] + l
# Prepends element 42 to l
l = [42] + l
我不喜欢另一种常见的方法l.insert(0, value)
,因为它需要一个幻数。此外,insert()
仅允许添加一个元素,但是上述方法具有添加一个或多个元素的相同语法。
答案 6 :(得分:0)
让我们来看看 4 种方法
>>>
>>> l = list(range(5))
>>> l
[0, 1, 2, 3, 4]
>>> l.insert(0, 5)
>>> l
[5, 0, 1, 2, 3, 4]
>>>
>>>
>>> l = list(range(5))
>>> l
[0, 1, 2, 3, 4]
>>> l = [5] + l
>>> l
[5, 0, 1, 2, 3, 4]
>>>
>>>
>>> l = list(range(5))
>>> l
[0, 1, 2, 3, 4]
>>> l[:0] = [5]
>>> l
[5, 0, 1, 2, 3, 4]
>>>
>>>
>>> from collections import deque
>>>
>>> l = list(range(5))
>>> l
[0, 1, 2, 3, 4]
>>> l = deque(l)
>>> l.appendleft(5)
>>> l = list(l)
>>> l
[5, 0, 1, 2, 3, 4]
>>>