¿Cuál es la sintaxis idiomática para pasar a una lista corta de python?
prepend (5)
¿Cuál es la sintaxis idiomática para pasar a una lista corta de python?
Por lo general, no es necesario que se anteponga repetitivamente a una lista en Python.
Si es corto , y no lo estás haciendo mucho ... entonces está bien.
list.insert
El list.insert
se puede utilizar de esta manera.
list.insert(0, x)
Pero esto es ineficiente, porque en Python, una list
es una matriz de punteros, y Python ahora debe tomar todos los punteros de la lista y moverlos hacia abajo uno a uno para insertar el puntero a su objeto en la primera ranura, así que esto es realmente solo Eficiente para listas bastante cortas, como pides.
Si desea un contenedor que sea eficiente para anteponer elementos, desea una lista con doble enlace. Python tiene uno, se llama deque
.
deque.appendleft
Una collections.deque
tiene muchos de los métodos de una lista. list.sort
es una excepción, por lo que definitivamente el deque
no es completamente Liskov sustituible por la list
.
>>> set(dir(list)) - set(dir(deque))
{''sort''}
El deque
también tiene un método de appendleft
(así como popleft
). El deque
es una cola de doble final y una lista doblemente enlazada: no importa la longitud, siempre se necesita la misma cantidad de tiempo para preparar algo. En notación O grande, O (1) versus el tiempo O (n) para las listas. Aquí está el uso:
>>> import collections
>>> d = collections.deque(''1234'')
>>> d
deque([''1'', ''2'', ''3'', ''4''])
>>> d.appendleft(''0'')
>>> d
deque([''0'', ''1'', ''2'', ''3'', ''4''])
deque.extendleft
También es relevante el método extendleft
de deque, que precedente iterativamente:
>>> from collections import deque
>>> d2 = deque(''def'')
>>> d2.extendleft(''cba'')
>>> d2
deque([''a'', ''b'', ''c'', ''d'', ''e'', ''f''])
Tenga en cuenta que cada elemento se agregará de uno en uno, invirtiendo así su orden.
Rendimiento de list
versus deque
Primero configuramos con algunos prependientes iterativos:
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
y rendimiento:
>>> 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
El deque es mucho más rápido. A medida que las listas se alargan, esperaría que un deque se desempeñe aún mejor. Si puede usar el extendleft
de extendleft
, probablemente obtendrá el mejor rendimiento de esa manera.
list.append()
es la opción obvia para agregar al final de una lista. Aquí hay una explicación razonable para la lista que list.prepend()
. Suponiendo que mi lista es corta y las preocupaciones de rendimiento son insignificantes, es
list.insert(0, x)
o
list[0:0] = [x]
¿idiomático?
El primero es sin duda mucho más claro y expresa la intención mucho mejor: solo desea insertar un elemento único, no una lista completa.
La forma s.insert(0, x)
es la más común.
Sin embargo, siempre que lo vea, puede ser el momento de considerar el uso de collections.deque lugar de una lista.
Si alguien encuentra esta pregunta como yo, aquí están mis pruebas de rendimiento de los métodos propuestos:
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
Como puede ver, la asignación de inserciones y segmentos es casi dos veces más rápida que la adición explícita y los resultados son muy similares. Como Raymond Hettinger señaló que el insert
es una opción más común y yo, personalmente, prefiero esta forma de prepararlo para la lista.
Si puedes seguir el camino funcional, lo siguiente es bastante claro.
new_list = [x] + your_list
Por supuesto, no ha insertado x
en su your_list
, sino que ha creado una nueva lista con x
preinstalada en ella.