Quelle est la syntaxe idiomatique pour ajouter à une courte liste python?
Vous ne voulez généralement pas ajouter de manière répétitive à une liste en Python.
Si c'est court et que tu ne le fais pas beaucoup ... alors ok.
list.insert
Le list.insert
peut être utilisé de cette façon.
list.insert(0, x)
Mais cela est inefficace, car en Python, un list
est un tableau de pointeurs, et Python doit maintenant prendre chaque pointeur de la liste et le déplacer vers le bas d'un pour insérer le pointeur sur votre objet dans le premier emplacement, donc ce n'est vraiment efficace pour des listes assez courtes, comme vous le demandez.
Voici un extrait de la source CPython où cela est implémenté - et comme vous pouvez le voir, nous commençons à la fin du tableau et déplaçons tout par le bas pour chaque insertion:
for (i = n; --i >= where; )
items[i+1] = items[i];
Si vous voulez un conteneur / une liste efficace pour ajouter des éléments, vous voulez une liste liée. Python a une liste doublement liée, qui peut être insérée au début et à la fin rapidement - elle s'appelle a deque
.
deque.appendleft
A collections.deque
possède de nombreuses méthodes d'une liste. list.sort
est une exception, ce qui rend deque
définitivement pas entièrement Liskov substituable à list
.
>>> set(dir(list)) - set(dir(deque))
{'sort'}
Le a deque
également une appendleft
méthode (ainsi que popleft
). Il deque
s'agit d'une file d'attente à double extrémité et d'une liste à double liaison - quelle que soit la longueur, il faut toujours autant de temps pour préparer quelque chose. En grande notation O, O (1) par rapport au 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
La extendleft
méthode deque , qui préfère itérativement:
>>> 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 à la fois, inversant ainsi efficacement leur ordre.
Performance de list
versusdeque
D'abord, nous configurons avec un préfixe itératif:
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 performance:
>>> 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'attendrais à ce qu'un deque fonctionne encore mieux. Si vous pouvez utiliser deque, extendleft
vous obtiendrez probablement les meilleures performances de cette façon.