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.insertpeut ê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.dequepossède de nombreuses méthodes d'une liste. list.sortest une exception, ce qui rend dequedéfinitivement pas entièrement Liskov substituable à list.
>>> set(dir(list)) - set(dir(deque))
{'sort'}
Le a dequeégalement une appendleftméthode (ainsi que popleft). Il deques'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 extendleftmé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 listversusdeque
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, extendleftvous obtiendrez probablement les meilleures performances de cette façon.