Python append () frente al operador + en las listas, ¿por qué dan resultados diferentes?

113

¿Por qué estas dos operaciones ( append()resp. +) Dan resultados diferentes?

>>> c = [1, 2, 3]
>>> c
[1, 2, 3]
>>> c += c
>>> c
[1, 2, 3, 1, 2, 3]
>>> c = [1, 2, 3]
>>> c.append(c)
>>> c
[1, 2, 3, [...]]
>>> 

En el último caso, en realidad hay una recursividad infinita. c[-1]y cson iguales. ¿Por qué es diferente con la +operación?

ooboo
fuente
1
con el debido respeto a una nueva pregunta viable: volví a la pregunta original para mantenerla limpia (1 pregunta por hilo, ver SO FAQ). Pregunte una nueva o haga preguntas de seguimiento dentro de los hilos de comentarios debajo de cada respuesta. Nota: sus ediciones no se pierden, haga clic en el historial y puede copiarlo / pegarlo en una nueva pregunta.
Abel
Similar para +=: stackoverflow.com/questions/725782/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
parece que da diferentes ans, pero no así. Si desea agregar un valor usando el operador +, debe usar el signo []. c + = [c] le dará el mismo resultado que anexar.
Sharif Chowdhury
@SharifChowdhury Creo que obtendrás el mismo resultado
trustory

Respuestas:

142

Para explicar "por qué":

La +operación agrega los elementos de la matriz a la matriz original. La array.appendoperación inserta la matriz (o cualquier objeto) al final de la matriz original, lo que da como resultado una referencia a sí mismo en ese lugar (de ahí la recursividad infinita).

La diferencia aquí es que la operación + actúa de manera específica cuando agrega una matriz (está sobrecargada como otras, vea este capítulo sobre secuencias) al concatenar el elemento. Sin embargo, el método append hace literalmente lo que le pides: agrega el objeto en el lado derecho que le das (la matriz o cualquier otro objeto), en lugar de tomar sus elementos.

Una alternativa

Úselo extend()si desea usar una función que actúe de manera similar al operador + (como otros también lo han mostrado aquí). No es prudente hacer lo contrario: tratar de imitar anexar con el operador + para listas (consulte mi enlace anterior sobre por qué).

Poca historia

Para divertirse, un poco de historia: el nacimiento del módulo de arreglos en Python en febrero de 1993. Puede que te sorprenda, pero los arreglos se agregaron mucho después de que aparecieran las secuencias y listas.

Abel
fuente
2
+1 porque siempre doy mi voto a favor de la información precisa. ¡Los enlaces a documentos oficiales son siempre una ventaja!
jathanismo
10
Otra parte del "por qué": las personas cuerdas esperan +ser simétricas: concatenar lista con lista.
Beni Cherniavsky-Paskin
1
+1, Buen punto Beni (aunque podría considerarlo como "sensato" decir "el objeto en el lado derecho se adjunta a la matriz en el lado izquierdo", pero personalmente encuentro el comportamiento actual más sensato).
Abel
si un elemento es una sola cadena, por ejemplo, s = 'palabra', l = ['esto', 'es']. Entonces l.append (s) y l + s deberían ser iguales. ¿Estoy en lo correcto?
user3512680
23

El operador de concatenación +es un operador infijo binario que, cuando se aplica a listas, devuelve una nueva lista que contiene todos los elementos de cada uno de sus dos operandos. El list.append()método es un mutatoren el listque agrega su único objectargumento (en su ejemplo específico, la lista c) al tema list. En su ejemplo, esto da como resultado que se cagregue una referencia a sí mismo (de ahí la recursividad infinita).

Una alternativa a la concatenación '+'

El list.extend()método es también un método mutador que concatena su sequenceargumento con el sujeto list. Específicamente, agrega cada uno de los elementos de sequenceen orden de iteración.

Un aparte

Al ser un operador, +devuelve el resultado de la expresión como un nuevo valor. Al ser un mutatormétodo no encadenado , list.extend()modifica la lista de temas en el lugar y no devuelve nada.

Matrices

Agregué esto debido a la posible confusión que la respuesta de Abel anterior puede causar al mezclar la discusión de listas, secuencias y matrices. Arraysse agregaron a Python después de las secuencias y listas, como una forma más eficiente de almacenar matrices de tipos de datos integrales. No confunda arrayscon lists. Ellos no son los mismos.

De los documentos de la matriz :

Las matrices son tipos de secuencia y se comportan de manera muy parecida a las listas, excepto que el tipo de objetos almacenados en ellas está restringido. El tipo se especifica en el momento de la creación del objeto mediante un código de tipo, que es un solo carácter.

Dave
fuente
18

appendes agregar un elemento a una lista. si desea ampliar la lista con la nueva lista que necesita utilizar extend.

>>> c = [1, 2, 3]
>>> c.extend(c)
>>> c
[1, 2, 3, 1, 2, 3]
SilentGhost
fuente
4
Pensé que está bastante claro por qué los resultados son diferentes, ¡porque las operaciones no son las mismas! si apareciera eso +y extendprodujera resultados diferentes, tendríamos algo en qué pensar.
SilentGhost
1
+1: Por qué no me gustan las preguntas "por qué": appendy +son diferentes. Es por eso. Me gusta esta respuesta porque ofrece qué hacer que tiene más sentido.
S.Lott
¿No trata este sitio de responder a las preguntas formuladas? La gente pregunta por qué PHP se llama PHP y por qué __lt__no se puede sobrecargar en Python (hoy en día sí). Las preguntas por qué son las más esenciales, pero a menudo las más difíciles de responder: piden la esencia, no un puntero al manual. Y por supuesto: si no le gusta una pregunta (a mí no me gusta la mayoría), entonces no responda ;-)
Abel
Para una demostración adicional, tal vez mostrar c += [c]y c.append(c[:])también.
ephemient
2
@Abel: ¿Por qué a+b != a*b? Son operaciones diferentes. Esa es la respuesta. "Por qué" no es tan útil como otras preguntas, como "¿Cómo puedo agregar correctamente?" O "¿Qué tiene de malo este apéndice que conduce a la recursividad infinita?" Preguntas del formulario "¿Qué le hago a X" o "Qué salió mal cuando hice X"? O "¿Qué debo hacer en lugar de X?" También ayudará a alguien a aprender, pero proporcionará respuestas enfocadas, utilizables y procesables.
S.Lott
8

Las listas de Python son heterogéneas, es decir, los elementos de la misma lista pueden ser cualquier tipo de objeto. La expresión: c.append(c)agrega el objeto ca la lista. En el caso de que haga que la propia lista sea miembro de la lista.

La expresión c += csuma dos listas juntas y asigna el resultado a la variable c. El +operador sobrecargado se define en las listas para crear una nueva lista cuyo contenido son los elementos de la primera lista y los elementos de la segunda lista.

Entonces, estas son realmente diferentes expresiones que se usan para hacer diferentes cosas por diseño.

Tendayi Mawushe
fuente
7

El método que estás buscando es extend(). De la documentación de Python :

list.append(x)
    Add an item to the end of the list; equivalent to a[len(a):] = [x].

list.extend(L)
    Extend the list by appending all the items in the given list; equivalent to a[len(a):] = L.

list.insert(i, x)
    Insert an item at a given position. The first argument is the index of the element before which to insert, so a.insert(0, x) inserts at the front of the list, and a.insert(len(a), x) is equivalent to a.append(x).
Chinmay Kanchi
fuente
3

deberías usar extend ()

>>> c=[1,2,3]
>>> c.extend(c)
>>> c
[1, 2, 3, 1, 2, 3]

otra información: agregar vs. extender

ghostdog74
fuente
2

Ver la documentación :

list.append (x)

  • Agregue un elemento al final de la lista; equivalente a [len (a):] = [x].

list.extend (L): amplía la lista agregando todos los elementos de la lista dada; equivalente a [len (a):] = L.

c.append(c)"añade" c a sí mismo como un elemento . Dado que una lista es un tipo de referencia, esto crea una estructura de datos recursiva.

c += ces equivalente a extend(c), que añade los elementos de c a c.

oefe
fuente