Каков идиоматический синтаксис для добавления в короткий список python?


list.append() является очевидным выбором для добавления в конец списка. Вот это разумное объяснение для пропавших без вести list.prepend(). Предполагая, что мой список короткий и проблемы с производительностью незначительны, это

list.insert(0, x)

или

list[0:0] = [x]

идиоматическое?

5 391

5 ответов:

на s.insert(0, x) форма является наиболее распространенной.

всякий раз, когда вы видите его, Хотя, это может быть время, чтобы рассмотреть возможность использования коллекций.дек вместо списка.

если вы можете пойти функциональным путем, следующее довольно ясно

new_list = [x] + your_list

конечно, вы не вводили x на your_list, а вы создали новый список x preprended к нему.

Если кто-то находит этот вопрос, как я, вот мои тесты производительности предлагаемых методов:

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 является более распространенным вариантом,и я лично предпочитаю этот способ добавить в список.

каков идиоматический синтаксис для добавления к короткому списку python?

обычно вы не хотите повторно добавлять список в Python.

если это короче, а вы не делаете это много... тогда ладно.

list.insert

The list.insert можно использовать таким образом.

list.insert(0, x)

но это неэффективно, потому что в Python,list - это массив указателей, и Теперь Python должен взять каждый указатель в списке и переместить его вниз на один, чтобы вставить указатель на ваш объект в первый слот, поэтому это действительно эффективно только для довольно коротких списков, как вы просите.

если вам нужен контейнер, который эффективен при добавлении элементов, вам нужен двусвязный список. У Python есть один-он называется a deque.

deque.appendleft

A collections.deque имеет много методов списка. list.sort исключение, что делает deque окончательно не полностью Лисков заменяется на list.

>>> set(dir(list)) - set(dir(deque))
{'sort'}

The 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 метод, который итеративно добавляет:

>>> 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 вы, вероятно, получите лучшая производительность таким образом.

первый, конечно, намного яснее и выражает намерение намного лучше: вы хотите вставить только один элемент, а не весь список.