list.append()
est le choix évident pour ajouter à la fin d'une liste. Voici une explication raisonnable pour le list.prepend()
manquant. En supposant que ma liste soit courte et que les problèmes de performances soient négligeables,
list.insert(0, x)
ou
list[0:0] = [x]
idiomatique?
La forme s.insert(0, x)
est la plus courante.
Cependant, chaque fois que vous le voyez, il est temps d’envisager d’utiliser un collections.deque au lieu d’une liste.
Si vous pouvez aller de manière fonctionnelle, ce qui suit est assez clair
new_list = [x] + your_list
Bien sûr, vous n'avez pas inséré x
dans your_list
, vous avez plutôt créé une nouvelle liste avec x
pré-programmée.
Quelle est la syntaxe idiomatique à utiliser pour ajouter une liste courte python?
En règle générale, vous ne voulez pas ajouter de liste répétitive à une liste en Python.
Si c'est court , et que vous ne le faites pas beaucoup ... alors ok.
list.insert
Le list.insert
peut être utilisé de cette façon.
list.insert(0, x)
Mais ceci 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 d'un point vers le bas pour l'insérer dans votre objet. dans le premier emplacement, ce n’est donc efficace que pour des listes plutôt courtes, comme vous le demandez.
Voici un extrait de la source CPython où cela est implémenté - et comme vous pouvez le constater, nous commençons à la fin du tableau et déplaçons le tout d'un vers le bas pour chaque insertion:
for (i = n; --i >= where; )
items[i+1] = items[i];
Si vous voulez un conteneur/une liste qui soit efficace pour ajouter des éléments, vous voulez une liste chaînée. Python a une liste doublement chaînée, qui peut être insérée au début et à la fin rapidement - elle s'appelle un deque
.
deque.appendleft
Un collections.deque
a beaucoup des méthodes d'une liste. list.sort
est une exception, rendant deque
définitivement pas entièrement Liskov substituable à list
.
>>> set(dir(list)) - set(dir(deque))
{'sort'}
La deque
possède également une méthode appendleft
(ainsi que popleft
). La deque
est une file d'attente à double extrémité et une liste à double liaison - quelle que soit leur longueur, il faut toujours le même temps pour préparer quelque chose. En grosse notation O, O(1) par rapport à la durée 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 méthode extendleft
de deque, également précieuse par itération:
>>> 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 à un, inversant ainsi leur ordre.
list
versus deque
Premièrement, nous installons avec un peu de prépresse itérative:
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
La deque est beaucoup plus rapide. Au fur et à mesure que les listes s'allongent, je m'attendrais à ce qu'une deque se comporte encore mieux. Si vous pouvez utiliser extendleft
de deque, vous obtiendrez probablement la meilleure performance de cette façon.
Si quelqu'un trouve cette question comme moi, voici mes tests de performance des méthodes proposées:
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
Comme vous pouvez le constater, insert
et l’attribution de tranches sont presque deux fois plus rapides que l’ajout explicite et sont très proches dans les résultats. Comme Raymond Hettinger noté insert
est une option plus commune et je préfère personnellement cette façon de préfixer à la liste.
Le premier est certainement beaucoup plus clair et exprime bien mieux l'intention: vous voulez seulement insérer un seul élément, pas une liste complète.