En Python, ¿cuál es la diferencia entre “.append ()” y “+ = []”?

Respuestas:

161

En su caso, la única diferencia es el rendimiento: agregar es dos veces más rápido.

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 el caso general append, agregará un elemento a la lista, mientras +=que copiará todos los elementos de la lista del lado derecho en la lista del lado izquierdo.

Actualización: análisis de rendimiento

Comparando códigos de bytes podemos suponer que la appendversión desperdicia ciclos en LOAD_ATTR+ CALL_FUNCTION, y + = versión - en BUILD_LIST. Aparentemente BUILD_LISTpesa más que 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

Podemos mejorar el rendimiento aún más eliminando los LOAD_ATTRgastos generales:

>>> timeit.Timer('a("something")', 's = []; a = s.append').timeit()
0.15924410999923566
Constantin
fuente
12
+1: Esto es muy interesante. Yo uso append de todos modos, porque da como resultado un código más claro. Pero no me di cuenta de que había una diferencia de rendimiento. En todo caso, hubiera esperado que la agregación fuera más lenta, ya que es una llamada de función garantizada, mientras que supuse que + = se optimizaría aún más.
DNS
2
¿No hay también una diferencia funcional? Por ejemplo, deje a = [] , b = [4,5,6] , aquí si hace c = a.append (b) entonces c sería una lista de lista [[4,5,6]] mientras que c + = b ; conduciría a una lista simple c = [4,5,6] .
rph
solo para aclarar las cosas: + = ofrece un mejor rendimiento que extender o agregar siempre que su entrada esté en el formato correcto. Lo que lleva tiempo en el ejemplo actual es la creación de la lista ['algo']. + = es aproximadamente un 15% más rápido
Joe
@Joe Si está comparando appendvs +=, entonces debe incluir la creación de la lista como parte de la medición. De lo contrario, sería una pregunta diferente ( extendvs +=).
jamesdlin
@jamesdlin ¡sí! Pero es fácil equivocarse a menos que ya lo sepas. Un poco de precisión adicional nunca ha hecho daño a nadie, ¿verdad?
Joe
48

En el ejemplo que dio, no hay diferencia, en términos de producción, entre append y +=. Pero hay una diferencia entre appendy +(sobre la que se preguntó originalmente).

>>> 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

Como puede ver, appendy +=tiene el mismo resultado; agregan el elemento a la lista, sin producir una nueva lista. Utilizando+ agrega las dos listas y produce una nueva lista.

DNS
fuente
Hay una diferencia entre agregar y + =.
Constantin
3
Existe el hecho de que appendagrega una entrada a la lista, mientras que + = agrega tantas como haya en la otra lista (es decir, alias a extend). Pero eso ya lo sabe, a juzgar por la forma en que se escribió la pregunta. ¿Hay alguna otra diferencia que me falta?
DNS
1
Hay una diferencia porque una asignación aumentada introduce la revinculación (explicación en mi respuesta).
Bobince
42
>>> a=[]
>>> a.append([1,2])
>>> a
[[1, 2]]
>>> a=[]
>>> a+=[1,2]
>>> a
[1, 2]

Vea que append agrega un solo elemento a la lista, que puede ser cualquier cosa. +=[]se une a las listas.

dwc
fuente
2
Votar esto porque es una distinción importante entre los dos. Buen trabajo.
31

+ = es una tarea. Cuando lo usas, realmente estás diciendo 'alguna_lista2 = alguna_lista2 + [' algo ']'. Las asignaciones implican volver a enlazar, por lo que:

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

El operador + = también debería normalmente crear un nuevo objeto de lista como lo hace normalmente list + list:

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

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

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

Sin embargo, en realidad:

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

Esto se debe a que las listas de Python implementan __iadd __ () para hacer un cortocircuito de asignación aumentada + = y llamar a list.extend () en su lugar. (Es un poco extraño esto: generalmente hace lo que querías decir, pero por razones confusas).

En general, si está agregando / extendiendo una lista existente y desea mantener la referencia a la misma lista (en lugar de hacer una nueva), es mejor ser explícito y seguir con append () / extend () métodos.

bobince
fuente
21
 some_list2 += ["something"]

es en realidad

 some_list2.extend(["something"])

por un valor, no hay diferencia. La documentación establece que:

s.append(x) lo mismo que lo s[len(s):len(s)] = [x]
s.extend(x) mismo ques[len(s):len(s)] = x

Así, obviamente, s.append(x)es lo mismo ques.extend([x])

vartec
fuente
s.append toma un tipo arbitrario y lo agrega a la lista; Es un verdadero apéndice. s.extend toma un iterable (generalmente una lista) y fusiona el iterable en s, modificando las direcciones de memoria de s. No son iguales.
W4t3randWind
9

La diferencia es que concatenar aplanará la lista resultante, mientras que añadir mantendrá los niveles intactos:

Entonces, por ejemplo, con:

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

Usando append, terminas con una lista de listas:

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

Al usar concatenar en su lugar, terminas con una lista plana:

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

Las pruebas de rendimiento aquí no son correctas:

  1. No debe ejecutar el perfil solo una vez.
  2. Si compara append con + = [] número de veces, debe declarar append como una función local.
  3. los resultados de tiempo son diferentes en diferentes versiones de Python: 64 y 32 bits

p.ej

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

buenas pruebas se pueden encontrar aquí: http://markandclick.com/1/post/2012/01/python-list-append-vs.html

Miguel
fuente
aún así, las pruebas + = en esa página usan += [one_var]. Si omitimos la creación de listas, + = se convierte en la opción más rápida.
Joe
3

Además de los aspectos descritos en las otras respuestas, agregar y + [] tienen comportamientos muy diferentes cuando intentas crear una lista de listas.

>>> 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'] agrega '5' y '6' a list1 como elementos individuales. list1.append (['5', '6']) agrega la lista ['5', '6'] a list1 como un solo elemento.

Chris Upchurch
fuente
2

El comportamiento de reenlace mencionado en otras respuestas es importante en ciertas circunstancias:

>>> 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

Esto se debe a que la asignación aumentada siempre se vuelve a enlazar, incluso si el objeto se mutó en el lugar. La revinculación aquí resulta ser a[1] = *mutated list*, que no funciona para tuplas.

Reincorporar a Monica
fuente
0

tomemos un ejemplo primero

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
fuente
0

El método append () agrega un solo elemento a la lista existente

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

Así que aquí se modificará some_list1.

Actualizado:

Mientras que se usa + para combinar los elementos de las listas (más de un elemento) en la lista existente de forma similar a la extensión (corregida por Flux ).

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

Así que aquí some_list2 y ["algo"] son ​​las dos listas que se combinan.

Naveen Verma
fuente
1
Esto está mal. +=no devuelve una nueva lista. El FAQ de programación dice: "... para listas, __iadd__es equivalente a llamar extenda la lista y devolver la lista. Por eso decimos que para listas, +=es una" abreviatura "de list.extend". También puede ver esto por sí mismo en el código fuente de CPython: github.com/python/cpython/blob/v3.8.2/Objects/…
Flux
0

"+" no cambia la lista

.append () muta la lista anterior

Andres
fuente