Quelle est la syntaxe idiomatique pour précéder une courte liste en Python ?
En général, en Python, vous n'avez pas envie d'ajouter de façon répétitive des éléments à une liste.
Si c'est court et que vous ne le faites pas souvent... alors c'est bon.
list.insert
El list.insert
peut être utilisé de cette façon.
list.insert(0, x)
Mais c'est inefficace, car en Python, un fichier list
est un tableau de pointeurs, et Python doit maintenant prendre chaque pointeur de la liste et le déplacer vers le bas d'une unité pour insérer le pointeur de votre objet dans le premier slot, donc ceci n'est vraiment efficace que pour des listes plutôt courtes, comme vous le demandez.
Voici un extrait à partir de la source CPython où cela est mis en œuvre - et comme vous pouvez le voir, nous commençons à la fin du tableau et nous déplaçons tout vers le bas d'une unité pour chaque insertion :
for (i = n; --i >= where; )
items[i+1] = items[i];
Si vous voulez un conteneur/une liste qui est efficace pour ajouter des éléments, vous voulez une liste liée. Python dispose d'une liste doublement liée, qui permet d'insérer rapidement des éléments au début et à la fin de la liste - c'est ce qu'on appelle un deque
.
deque.appendleft
A collections.deque
possède plusieurs des méthodes d'une liste. list.sort
est une exception, ce qui rend deque
définitivement non entièrement substituable à Liskov list
.
>>> set(dir(list)) - set(dir(deque))
{'sort'}
El deque
a également un appendleft
(ainsi que la méthode popleft
). Le site deque
est une file d'attente à double extrémité et une liste doublement liée - quelle que soit sa longueur, il faut toujours le même temps pour préprendre quelque chose. En notation grand O, O(1) contre le temps O(n) pour les listes. Voici l'utilisation :
>>> import collections
>>> d = collections.deque('1234')
>>> d
deque(['1', '2', '3', '4'])
>>> d.appendleft('0')
>>> d
deque(['0', '1', '2', '3', '4'])
deque.extendleft
Il faut également tenir compte de l'élément deque extendleft
qui précède de façon itérative :
>>> from collections import deque
>>> d2 = deque('def')
>>> d2.extendleft('cba')
>>> d2
deque(['a', 'b', 'c', 'd', 'e', 'f'])
Notez que chaque élément sera ajouté un par un, ce qui inversera leur ordre.
Performance de list
contre deque
Tout d'abord, nous mettons en place un système itératif de préparation :
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
et les performances :
>>> 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
Le deque est beaucoup plus rapide. À mesure que les listes s'allongent, je m'attends à ce que les performances d'un deque soient encore meilleures. Si vous pouvez utiliser la fonction deque extendleft
vous obtiendrez probablement les meilleures performances de cette façon.