En Python, quelle est la différence entre «.append ()» et «+ = []»?

122

Quelle est la différence entre:

some_list1 = []
some_list1.append("something")

et

some_list2 = []
some_list2 += ["something"]
Nan
la source
3
ajouter si pour un seul élément. peut-être que tu veux dire extend.
hasen
Pour le cas le plus intéressant de +=vs extend: stackoverflow.com/questions/3653298/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
+=vs append stackoverflow.com/q/252703/6674599
Semnodime

Réponses:

161

Pour votre cas, la seule différence est la performance: l'ajout est deux fois plus rapide.

Python 3.0 (r30:67507, Dec  3 2008, 20:14:27) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> timeit.Timer('s.append("something")', 's = []').timeit()
0.20177424499999999
>>> timeit.Timer('s += ["something"]', 's = []').timeit()
0.41192320500000079

Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> timeit.Timer('s.append("something")', 's = []').timeit()
0.23079359499999999
>>> timeit.Timer('s += ["something"]', 's = []').timeit()
0.44208112500000141

En général append, ajoutera un élément à la liste, tandis que +=copiera tous les éléments de la liste de droite dans la liste de gauche.

Mise à jour: analyse des performances

En comparant les bytecodes, nous pouvons supposer que la appendversion gaspille des cycles en LOAD_ATTR+ CALL_FUNCTIONet + = version - en BUILD_LIST. Apparemment, l' BUILD_LISTemporte sur LOAD_ATTR+ CALL_FUNCTION.

>>> import dis
>>> dis.dis(compile("s = []; s.append('spam')", '', 'exec'))
  1           0 BUILD_LIST               0
              3 STORE_NAME               0 (s)
              6 LOAD_NAME                0 (s)
              9 LOAD_ATTR                1 (append)
             12 LOAD_CONST               0 ('spam')
             15 CALL_FUNCTION            1
             18 POP_TOP
             19 LOAD_CONST               1 (None)
             22 RETURN_VALUE
>>> dis.dis(compile("s = []; s += ['spam']", '', 'exec'))
  1           0 BUILD_LIST               0
              3 STORE_NAME               0 (s)
              6 LOAD_NAME                0 (s)
              9 LOAD_CONST               0 ('spam')
             12 BUILD_LIST               1
             15 INPLACE_ADD
             16 STORE_NAME               0 (s)
             19 LOAD_CONST               1 (None)
             22 RETURN_VALUE

Nous pouvons encore améliorer les performances en supprimant les LOAD_ATTRfrais généraux:

>>> timeit.Timer('a("something")', 's = []; a = s.append').timeit()
0.15924410999923566
Constantin
la source
12
+1: C'est très intéressant. J'utilise quand même append, car il en résulte un code plus clair. Mais je ne savais pas qu'il y avait une différence de performance. Si quoi que ce soit, je me serais attendu à ce que l'append soit plus lent, car il s'agit d'un appel de fonction garanti, alors que j'ai supposé que + = serait optimisé davantage.
DNS
2
N'y a-t-il pas aussi une différence fonctionnelle? Par exemple, laissez a = [] , b = [4,5,6] , ici si vous faites c = a.append (b) alors c serait une liste de liste [[4,5,6]] tandis que c + = b ; conduirait à une simple liste c = [4,5,6] .
rph
juste pour mettre les choses au clair: + = donne de meilleures performances que l'extension ou l'ajout tant que votre entrée est dans le bon format. Ce qui prend du temps dans l'exemple actuel, c'est la création de la liste ['something']. + = est environ 15% plus rapide
Joe
@Joe Si vous comparez appendvs +=, vous devez inclure la création de la liste dans le cadre de la mesure. Sinon, ce serait une question différente ( extendvs +=).
jamesdlin
@jamesdlin yup! Mais il est facile de se tromper à moins que vous ne le sachiez déjà. Un peu de précision supplémentaire n'a jamais fait de mal à personne, non?
Joe le
48

Dans l'exemple que vous avez donné, il n'y a pas de différence, en termes de rendement, entre appendet +=. Mais il y a une différence entre appendet +(que la question posait à l'origine).

>>> a = []
>>> id(a)
11814312
>>> a.append("hello")
>>> id(a)
11814312

>>> b = []
>>> id(b)
11828720
>>> c = b + ["hello"]
>>> id(c)
11833752
>>> b += ["hello"]
>>> id(b)
11828720

Comme vous pouvez le voir, appendet +=avoir le même résultat; ils ajoutent l'élément à la liste, sans produire de nouvelle liste. L'utilisation +ajoute les deux listes et produit une nouvelle liste.

DNS
la source
Il y a une différence entre append et + =.
Constantin
3
Il y a le fait qui appendajoute une entrée à la liste, tandis que + = en ajoute autant qu'il y en a dans l'autre liste (c'est-à-dire les alias de extend). Mais il / elle le sait déjà, à en juger par la manière dont la question a été écrite. Y a-t-il une autre différence qui me manque?
DNS
1
Il y a une différence car une affectation augmentée introduit une reliure (explication dans ma réponse).
bobince
42
>>> a=[]
>>> a.append([1,2])
>>> a
[[1, 2]]
>>> a=[]
>>> a+=[1,2]
>>> a
[1, 2]

Voir que append ajoute un seul élément à la liste, qui peut être n'importe quoi. +=[]rejoint les listes.

dwc
la source
2
Voter parce que c'est une distinction importante entre les deux. Bon travail.
31

+ = est une affectation. Quand vous l'utilisez, vous dites vraiment "une_liste2 = une_liste2 + [" quelque chose "]". Les affectations impliquent une nouvelle liaison, donc:

l= []

def a1(x):
    l.append(x) # works

def a2(x):
    l= l+[x] # assign to l, makes l local
             # so attempt to read l for addition gives UnboundLocalError

def a3(x):
    l+= [x]  # fails for the same reason

L'opérateur + = devrait également créer normalement un nouvel objet de liste comme le fait normalement list + list:

>>> l1= []
>>> l2= l1

>>> l1.append('x')
>>> l1 is l2
True

>>> l1= l1+['x']
>>> l1 is l2
False

Cependant en réalité:

>>> l2= l1
>>> l1+= ['x']
>>> l1 is l2
True

C'est parce que les listes Python implémentent __iadd __ () pour créer un court-circuit d'affectation + = augmenté et appeler à la place list.extend (). (C'est un peu une verrue étrange ceci: cela fait généralement ce que vous vouliez dire, mais pour des raisons déroutantes.)

En général, si vous ajoutez / étendez une liste existante et que vous souhaitez conserver la référence à la même liste (au lieu d'en créer une nouvelle), il est préférable d'être explicite et de vous en tenir à append () / extend () méthodes.

bobince
la source
21
 some_list2 += ["something"]

est en fait

 some_list2.extend(["something"])

pour une valeur, il n'y a pas de différence. La documentation indique que:

s.append(x) identique s[len(s):len(s)] = [x]
s.extend(x) às[len(s):len(s)] = x

C'est donc évidemment la s.append(x)même chose ques.extend([x])

vartec
la source
s.append prend un type arbitraire et l'ajoute à la liste; C'est un vrai ajout. s.extend prend un itérable (généralement une liste), et fusionne l'itérable dans s, en modifiant les adresses mémoire de s. Ce ne sont pas les mêmes.
W4t3randWind
9

La différence est que concaténer aplatit la liste résultante, tandis que append gardera les niveaux intacts:

Donc par exemple avec:

myList = [ ]
listA = [1,2,3]
listB = ["a","b","c"]

En utilisant append, vous vous retrouvez avec une liste de listes:

>> myList.append(listA)
>> myList.append(listB)
>> myList
[[1,2,3],['a',b','c']]

En utilisant concaténer à la place, vous vous retrouvez avec une liste plate:

>> myList += listA + listB
>> myList
[1,2,3,"a","b","c"]
SRC2
la source
5

Les tests de performance ici ne sont pas corrects:

  1. Vous ne devez pas exécuter le profil une seule fois.
  2. Si vous comparez append à + = [] nombre de fois, vous devez déclarer append comme une fonction locale.
  3. les résultats temporels sont différents selon les versions de python: 64 et 32 ​​bits

par exemple

timeit.Timer ('for i in xrange (100): app (i)', 's = []; app = s.append'). timeit ()

de bons tests peuvent être trouvés ici: http://markandclick.com/1/post/2012/01/python-list-append-vs.html

Michael
la source
encore, les tests + = dans cette page utilisent += [one_var]. Si nous omettons de créer des listes, + = devient l'option la plus rapide.
Joe
3

En plus des aspects décrits dans les autres réponses, ajouter et + [] ont des comportements très différents lorsque vous essayez de construire une liste de listes.

>>> list1=[[1,2],[3,4]]
>>> list2=[5,6]
>>> list3=list1+list2
>>> list3
[[1, 2], [3, 4], 5, 6]
>>> list1.append(list2)
>>> list1
[[1, 2], [3, 4], [5, 6]]

list1 + ['5', '6'] ajoute '5' et '6' à la liste1 en tant qu'éléments individuels. list1.append (['5', '6']) ajoute la liste ['5', '6'] à la liste1 en tant qu'élément unique.

Chris Upchurch
la source
2

Le comportement de réengagement mentionné dans d'autres réponses a de l'importance dans certaines circonstances:

>>> a = ([],[])
>>> a[0].append(1)
>>> a
([1], [])
>>> a[1] += [1]
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

En effet, l'affectation augmentée est toujours reliée, même si l'objet a été muté sur place. La reliure se trouve ici a[1] = *mutated list*, ce qui ne fonctionne pas pour les tuples.

Réintégrer Monica
la source
0

prenons d'abord un exemple

list1=[1,2,3,4]
list2=list1     (that means they points to same object)

if we do 
list1=list1+[5]    it will create a new object of list
print(list1)       output [1,2,3,4,5] 
print(list2)       output [1,2,3,4]

but if we append  then 
list1.append(5)     no new object of list created
print(list1)       output [1,2,3,4,5] 
print(list2)       output [1,2,3,4,5]

extend(list) also do the same work as append it just append a list instead of a 
single variable 
Avnish kumar
la source
0

La méthode append () ajoute un seul élément à la liste existante

some_list1 = []
some_list1.append("something")

Donc, ici, some_list1 sera modifié.

Actualisé:

Tandis que l'utilisation de + pour combiner les éléments de listes (plus d'un élément) dans la liste existante similaire à l'extension (comme corrigé par Flux ).

some_list2 = []
some_list2 += ["something"]

Alors ici, some_list2 et ["something"] sont les deux listes qui sont combinées.

Naveen Verma
la source
1
C'est faux. +=ne renvoie pas de nouvelle liste. La FAQ de programmation dit: "... pour les listes, __iadd__équivaut à appeler extendsur la liste et à renvoyer la liste. C'est pourquoi nous disons que pour les listes, +=c'est un" raccourci "pour list.extend". Vous pouvez également le voir par vous-même dans le code source de CPython: github.com/python/cpython/blob/v3.8.2/Objects/…
Flux
0

"+" ne modifie pas la liste

.append () mute l'ancienne liste

Andrés
la source