python list prepend

¿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.