Каков идиоматический синтаксис для добавления в короткий список Python?
Обычно вы не хотите повторяться перед списком в Python.
Если это короткий , и вы не делаете это много ... тогда хорошо.
list.insert
list.insert
можно использовать таким образом.
list.insert(0, x)
Но это неэффективно, потому что в Python list
- это массив указателей, и теперь Python должен взять каждый указатель в списке и переместить его вниз на один, чтобы вставить указатель на ваш объект в первом слоте, так что это действительно эффективно только для довольно коротких списков, как вы спрашиваете.
Если вам нужен контейнер, эффективный для добавления элементов, вам нужен список с двумя связями. У Python есть один - он называется deque
.
deque.appendleft
A collections.deque
имеет много методов списка. list.sort
является исключением, делая deque
окончательно не полностью заменяющим Лискова вместо 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
Также актуальным является метод extendleft
в deque, который итеративно добавляет:
>>> 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 будет работать еще лучше. Если вы можете использовать deque's extendleft
, вы, вероятно, получите лучшую производительность таким образом.