Какой идиоматический синтаксис для добавления в короткий список питонов?
list.append()
является очевидным выбором для добавления в конец списка. Вот разумное объяснение пропавшего без вести list.prepend()
, Если предположить, что мой список короткий и проблемы с производительностью незначительны,
list.insert(0, x)
или же
list[0:0] = [x]
идиоматическое?
9 ответов
s.insert(0, x)
форма является наиболее распространенным.
Когда бы вы ни увидели это, возможно, пришло время рассмотреть возможность использования collection.deque вместо списка.
Если вы можете пойти функциональным путем, следующее довольно ясно
new_list = [x] + your_list
Конечно, вы не вставили x
в your_list
скорее вы создали новый список с x
приготовился к этому.
Какой идиоматический синтаксис для добавления в короткий список питонов?
Обычно вы не хотите повторяться перед списком в Python.
Если оно короткое, и ты не часто этим занимаешься... тогда хорошо.
list.insert
list.insert
можно использовать таким образом.
list.insert(0, x)
Но это неэффективно, потому что в Python, list
является массивом указателей, и теперь Python должен взять каждый указатель в списке и переместить его вниз на единицу, чтобы вставить указатель на ваш объект в первом слоте, так что это действительно эффективно только для довольно коротких списков, как вы просите.
Если вам нужен контейнер, эффективный для добавления элементов, вам нужен список с двумя связями. У Python есть один - он называется deque
,
deque.appendleft
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
Также актуальным является deque's 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 будет работать еще лучше. Если вы можете использовать Deque's 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
и назначение среза почти в два раза быстрее, чем явное добавление, и очень близки по результатам. Как отметил Раймонд Хеттингер insert
это более распространенный вариант, и я, лично, предпочитаю этот способ, чтобы добавить в список.
На мой взгляд, наиболее элегантный и идиоматический способ добавления элемента или списка в другой список в 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()
позволяет добавлять только один элемент, однако описанный выше подход имеет тот же синтаксис для добавления одного или нескольких элементов в начале.
Первый, безусловно, намного понятнее и выражает намерение гораздо лучше: вы хотите вставить только один элемент, а не целый список.
Давайте рассмотрим 4 метода
- Использование insert ()
>>>
>>> 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]
>>>
- Использование collections.deque.appendleft()
>>>
>>> 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]
>>>
Я бы сделал что-то довольно быстро в python >= 3.0
list=[0,*list]
Возможно, это не самый эффективный способ, но, на мой взгляд, самый Pythonic.
Для небольшого списка вы можете использовать метод Insert(), чтобы добавить значение в список:
my_list = [2, 3, 4]
my_list.insert(0, 1)
Однако для больших списков может быть более эффективно использовать двухстороннюю очередь вместо списка:
from collections import deque
my_list = deque([2, 3, 4])
my_list.appendleft(1)
Деки — это структура данных, которая поддерживает эффективные операции добавления и добавления и обычно работает быстрее, чем списки для больших структур данных.