Quelle est la différence entre les méthodes de la liste append()
et extend()
?
Quelle est la différence entre extend
et en utilisant simplement l'opérateur d'addition - dans l'exemple ci-dessus, x = x + [4, 5]
?
Quelle est la différence entre les méthodes de la liste append()
et extend()
?
Quelle est la différence entre extend
et en utilisant simplement l'opérateur d'addition - dans l'exemple ci-dessus, x = x + [4, 5]
?
En fait, il y a un grande différence - x + [4, 5]
vous donne une nouvelle liste affectée à x - x.extend()
modifie la liste originale. Je développe dans ma réponse ci-dessous.
append
ajoute un élément à une liste, et extend
concatène la première liste avec une autre liste (ou un autre itérable, pas nécessairement une liste).
>>> li = ['a', 'b', 'mpilgrim', 'z', 'example']
>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li.append("new")
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new']
>>> li.append(["new", 2])
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new', ['new', 2]]
>>> li.insert(2, "new")
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', ['new', 2]]
>>> li.extend(["two", "elements"])
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', ['new', 2], 'two', 'elements']
Quelle est la différence entre les méthodes de liste append et extend ?
append
ajoute son argument comme un seul élément à la fin d'une liste. La longueur de la liste elle-même sera augmentée de un.extend
itère sur son argument en ajoutant chaque élément à la liste, étendant ainsi la liste. La longueur de la liste sera augmentée du nombre d'éléments présents dans l'argument itérable.append
Le site list.append
ajoute un objet à la fin de la liste.
my_list.append(object)
Quel que soit l'objet, qu'il s'agisse d'un nombre, d'une chaîne de caractères, d'une autre liste ou d'autre chose, il est ajouté à la fin de la commande my_list
comme une seule entrée dans la liste.
>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
Gardez donc à l'esprit qu'une liste est un objet. Si vous ajoutez une autre liste à une liste, la première liste sera un objet unique à la fin de la liste (ce qui n'est peut-être pas ce que vous voulez) :
>>> another_list = [1, 2, 3]
>>> my_list.append(another_list)
>>> my_list
['foo', 'bar', 'baz', [1, 2, 3]]
#^^^^^^^^^--- single item at the end of the list.
extend
Le site list.extend
étend une liste en ajoutant des éléments d'une table itérative :
my_list.extend(iterable)
Ainsi, avec extend, chaque élément de l'itérable est ajouté à la liste. Par exemple :
>>> my_list
['foo', 'bar']
>>> another_list = [1, 2, 3]
>>> my_list.extend(another_list)
>>> my_list
['foo', 'bar', 1, 2, 3]
Gardez à l'esprit qu'une chaîne est un itérable, donc si vous étendez une liste avec une chaîne, vous ajouterez chaque caractère au fur et à mesure que vous itérerez sur la chaîne (ce qui n'est peut-être pas ce que vous voulez) :
>>> my_list.extend('baz')
>>> my_list
['foo', 'bar', 1, 2, 3, 'b', 'a', 'z']
__add__
( +
) et __iadd__
( +=
)Les deux sites +
et +=
Les opérateurs sont définis pour list
. Ils sont sémantiquement similaires à extend.
my_list + another_list
crée une troisième liste en mémoire, de sorte que vous pouvez retourner le résultat de celle-ci, mais elle exige que le deuxième itérable soit une liste.
my_list += another_list
modifie la liste in-place (il est l'opérateur in-place, et les listes sont des objets mutables, comme nous l'avons vu), il ne crée donc pas une nouvelle liste. Il fonctionne également comme extend, dans la mesure où le second itérable peut être n'importe quel type d'itérable.
Ne vous embrouillez pas - my_list = my_list + another_list
n'est pas équivalent à +=
- cela vous donne une toute nouvelle liste assignée à ma_liste.
Append a ( amorti ) complexité temporelle constante , O(1).
Extend a une complexité temporelle, O(k).
L'itération à travers les multiples appels à append
ajoute à la complexité, la rendant équivalente à celle de extend, et puisque l'itération de extend est implémentée en C, elle sera toujours plus rapide si vous avez l'intention d'ajouter des éléments successifs d'une itérable à une liste.
En ce qui concerne le terme "amorti" - du source de mise en œuvre de l'objet de la liste :
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
Cela signifie que nous bénéficions d'emblée des avantages d'une réallocation de mémoire plus importante que nécessaire, mais que nous risquons de la payer lors de la prochaine réallocation marginale avec une réallocation encore plus importante. Le temps total pour tous les ajouts est linéaire à O(n), et le temps alloué par ajout, devient O(1).
Vous pouvez vous demander ce qui est le plus performant, puisque append peut être utilisé pour obtenir le même résultat que extend. Les fonctions suivantes font la même chose :
def append(alist, iterable):
for item in iterable:
alist.append(item)
def extend(alist, iterable):
alist.extend(iterable)
Alors, chronométrons-les :
import timeit
>>> min(timeit.repeat(lambda: append([], "abcdefghijklmnopqrstuvwxyz")))
2.867846965789795
>>> min(timeit.repeat(lambda: extend([], "abcdefghijklmnopqrstuvwxyz")))
0.8060121536254883
Un commentateur a dit :
Réponse parfaite, il me manque juste le timing de la comparaison en ajoutant un seul élément.
Faites la chose sémantiquement correcte. Si vous voulez ajouter tous les éléments d'un itérable, utilisez extend
. Si vous n'ajoutez qu'un seul élément, utilisez append
.
Ok, alors créons une expérience pour voir comment cela fonctionne dans le temps :
def append_one(a_list, element):
a_list.append(element)
def extend_one(a_list, element):
"""creating a new list is semantically the most direct
way to create an iterable to give to extend"""
a_list.extend([element])
import timeit
Et nous constatons que le fait de créer un itérable juste pour utiliser extend est une perte de temps (mineure) :
>>> min(timeit.repeat(lambda: append_one([], 0)))
0.2082819009956438
>>> min(timeit.repeat(lambda: extend_one([], 0)))
0.2397019260097295
Nous apprenons de cela qu'il n'y a rien à gagner à utiliser extend
alors que nous n'avons que un à ajouter.
De plus, ces horaires ne sont pas si importants. Je les montre simplement pour montrer qu'en Python, faire la chose sémantiquement correcte, c'est faire les choses de la manière suivante Droit Way™.
Il est possible de tester les temps de deux opérations comparables et d'obtenir un résultat ambigu ou inverse. Concentrez-vous sur l'exécution de l'opération sémantiquement correcte.
Nous voyons que extend
est sémantiquement plus clair, et qu'il peut s'exécuter beaucoup plus rapidement que le programme append
, lorsque vous avez l'intention d'ajouter chaque élément d'un itérable à une liste.
Si vous n'avez qu'un seul élément (ne faisant pas partie d'un itérable) à ajouter à la liste, utilisez la méthode suivante append
.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.