En Python, cuando a = [1,2,3,4]; b = a; b [0] = 7, esta declaración cambiará los elementos en a. ¿Por qué?

Porque b = a y a = [1,2,3,4] son declaraciones vinculantes . Evalúan una expresión a la derecha y vinculan los resultados a algún nombre a la izquierda.

Los resultados de la evaluación de la expresión son un objeto. El enlace es una referencia a ese objeto. [1,2,3,4] es una lista literal compuesta de una secuencia de valores literales enteros. En b = a, a es ya una simple referencia a un objeto, por lo que b se convierte en otra referencia al mismo objeto. Ahora son alias entre sí.

Si está familiarizado con la semántica del sistema de archivos Unx, a y b son como enlaces al mismo inodo. El objeto es como el contenido del archivo almacenado a través de ese inodo.

En general, esta distinción entre “” vincular nombres a referencias de objetos “versus” asignar valores a nombres de variables “solo es significativa cuando se trata de objetos mutables (listas, diccionarios, conjuntos, conjuntos de bytes, etc. ). Para objetos inmutables (números, cadenas de Python , etc. ) es simplemente un detalle de implementación que debería ser completamente transparente para los programadores.

Para una copia superficial de una lista, es suficiente usar un segmento: b = a [:] para evaluar todos los elementos de a en un nuevo objeto de lista y vincularlo al nuevo nombre b.

Esta comprensión de la referencia frente a la creación de instancias y la copia frente a la copia profunda (recursiva) y la evaluación ansiosa frente a la floja son temas que deberá aprender y apreciar a medida que aprenda Python, o cualquier otra forma avanzada de programación.

Bueno, esto es consecuencia de los punteros [1]. Para muchos lenguajes de programación, incluido Python, algunas estructuras de datos pueden no copiarse con el operador “=”. Esto se hace tan a menudo, que copiar una matriz completa (o la estructura que quería copiar) es demasiado lenta / ineficiente. En cambio, cuando escribes

b = a

lo que sucede es que a partir de ahí, b es solo otro nombre para a, es decir, no se otorgó una nueva ubicación de memoria a b, ahora la variable b apunta al mismo lugar que la variable a. Luego, cuando realiza cualquier otra operación a b, también lo está haciendo a a, ya que son la misma variable.

Este proceso no le sucede a todas las estructuras de datos. Normalmente, solo sucede con los complejos, como los arrays y los dictos. De hecho, el siguiente código generará el mismo problema:

a = {‘a’: 1, ‘b’: 2, ‘c’: 3}
b = a
b [‘a’] = 5
imprimir (a)

Para estructuras simples, como enteros y cadenas, el valor de la variable se copiará, por lo que b no será simplemente otro nombre para a, y no tendrá este problema.

Si desea copiar una matriz aa b sin que sean la misma variable, copie elemento por elemento, como aquí:

a = [1,2,3,4]
b = []
para yo en un:
b.append (i)

Esto hará lo que pretendes hacer.

Notas al pie

[1] Puntero (programación de computadora) – Wikipedia

En Python, cuando a = [1,2,3,4]; b = a; b [0] = 7, esta declaración cambiará los elementos en a. ¿Por qué?

Esto es fácil de entender una vez que lo analizas. Vamos a deconstruirlo una declaración a la vez …

a = [1, 2, 3, 4]

La declaración anterior crea una lista de cuatro elementos y asigna el nombre “a” para referirse a ella.

b = a

La declaración anterior hace que el nombre de la variable “b” se refiera a lo que sea que “a” se refiera. Por lo tanto, b ahora se refiere a la misma lista de cuatro elementos. b se convierte en un alias para a.

b [0] = 7

Recuerde que “b” ahora se refiere a la misma lista de cuatro elementos que “a” hace; por lo tanto, esta última declaración (justo arriba) asigna el valor 7 al primer elemento.

¿Qué pasaría si en su lugar quisiera que b se refiriera a una lista completamente separada y luego asignara 7 al primer elemento en ESA lista?

La respuesta es hacer que b se refiera a su propia copia de los datos en lugar de simplemente un alias para a. Aquí está la forma más fácil de hacerlo. Esto dice copiar una porción de a y crear una nueva matriz … y esa porción contiene toda la matriz …

b = a [:]

Por lo tanto, las siguientes tres líneas hacen lo que quieres:

a = [1, 2, 3, 4]
b = a [:]
b [0] = 7

Si imprime ayb, encontrará que ahora contienen datos diferentes.

imprimir (a)
imprimir (b)

Respuesta corta: porque las listas son objetos mutables.

Respuesta más larga:

En Python, realmente no tienes variables. Tienes objetos y nombres. O al menos, puede resultarle útil pensar en las cosas de esta manera. Ejemplos de objetos incluyen ints, flotantes, tuplas, listas y diccionarios.

De lo anterior, ints, flotadores y tuplas son inmutables. Eso significa que no puedes cambiarlos. Pero las listas y los diccionarios son mutables. Eso significa que los objetos se pueden cambiar.

Ejemplos de nombres son ayb en su código en la pregunta. Entonces, cuando dices a=[1,2,3,4] , estás diciendo “crea una lista y dale el nombre ‘a'”. Entonces, cuando dices b=a , estás diciendo “dale al objeto llamado ‘a’ el nombre ‘b’ también”.

Entonces, un pequeño cambio en su ejemplo anterior: intente lo siguiente.

a = (1,2,3,4)
b = a
b [0] = 7

Obtendrás un resultado diferente. Específicamente,

TypeError: el objeto ‘tupla’ no admite la asignación de elementos

Porque las tuplas son inmutables. No tienes permitido cambiarlos. Entonces intenta

b = (4,5,6,7)
imprimir a, b

Sin embargo, tenga en cuenta que no está cambiando el objeto nombrado por b en este segundo caso. Estás diciendo “crea una nueva tupla y dale el nombre ‘b'”. Entonces ahora tienes dos objetos diferentes con dos nombres diferentes

Las variables son referencias. Cuando crea la variable a = [1, 2, 3, 4], está creando una referencia a la lista [1, 2, 3, 4]. De manera similar, cuando asigna b = a, está creando una referencia a la variable a a través de la variable b. Por lo tanto, los cambios en b cambiarán el objeto subyacente: la lista [1, 2, 3, 4].

Su segunda situación hace que cree una referencia al valor uno en la variable a, y luego cree otra referencia al valor 1 a b asignando b = a. Sin embargo, luego usa b para crear una referencia diferente al valor 3, borrando su referencia al valor 1.

“Cambio” tiene dos significados, que son diferentes en Python. Llamémoslos “reemplazar” y “modificar” (la terminología de Python es “volver a unir” y “mutar”, pero no tiene por qué preocuparte).

Cuando reemplaza un objeto, lo deja ser, simplemente coloca otra cosa en su lugar, o mejor dicho, usa su nombre para otra cosa. Cuando reemplaza su automóvil, su automóvil antiguo aún existe, pero usted simplemente comienza a llamar a otro automóvil “mi automóvil”.

a = 1 significa que a es un nombre para un objeto 1. b = a significa que b es otro nombre para el mismo objeto. b = 3 significa que b ya no es un nombre para ese objeto, sino para otro objeto, 3. a, por supuesto, sigue siendo el nombre del mismo objeto; no ha cambiado a al reemplazar b.

Cuando modifica un objeto, sigue siendo el mismo objeto: acaba de cambiar (reemplazar o modificar) algunos _atributos_ o _componentes_ de él. Cuando pinta su automóvil de azul, sigue siendo el mismo, pero “mi automóvil” .color ahora es # 00f en lugar de lo que era antes.

a = [1,2,3,4] significa que a es un nombre para un objeto, una lista con cuatro elementos. b = a significa que b es un nombre para el mismo objeto. b [0] = 7 reemplaza el primer componente de b, modificando b, pero sigue siendo el mismo objeto. Entonces un [0] es el primer componente de ese mismo objeto, es decir, 7.

Espero que sea más claro ahora. Si tiene más preguntas, no dude en preguntar.

a = [1,2,3,4]

en el sistema ‘a’ tiene alguna dirección

cuando terminaste la asignación en Python, apuntó a esa dirección de la variable del lado derecho

como b = a significa que ahora b está apuntando a un

entonces ‘a’ y ‘b’ apuntan a la misma dirección de memoria cuando cambias en esa dirección usando cualquier variable que apunta a esa memoria, muestra cambios en todas las variables.

Básicamente es una operación de copia superficial.

SI no desea actualizar las otras variables

Entonces puedes usar el método deepcopy ()

solo importa la copia

a = [1,2,3,4]

b = copy.deepcopy (a)

cuando haces una copia profunda, asigna nueva memoria a esa variable

b [2] = 50

imprimir (b) >> [1,2,50,4]

imprimir (a) >> [1,2,3,4]

Primero, distingamos entre nombres y objetos. En su ejemplo, ayb son nombres, y [1,2,3,4] es el objeto (es un objeto de lista , para ser más específico). En Python, las listas son lo que llamaría objetos mutables (lo que significa que son objetos cuyo valor se puede cambiar). Aquí, tanto a como b están vinculados al mismo objeto de lista. Esto significa que puede cambiar el valor de ese objeto de lista (porque las listas son mutables) utilizando cualquiera de los nombres a o b . Puede decir a [0] = 7 o b [0] = 7 , y en cualquier caso, terminaría cambiando el mismo objeto de lista. Es como hablar con una persona que tiene dos nombres diferentes. Puedes dirigirte a él como Robert o Bob, y él te respondería de cualquier manera.

Los enteros, por otro lado, son objetos inmutables . Sus valores no pueden ser cambiados. Digamos que tienes:

a = 5

a + = 2

Aquí, NO está cambiando realmente el valor de 5. El objeto entero 5 siempre será 5. Lo que sucede aquí, en cambio, es que se agrega 2 a 5, lo que nos da un nuevo número entero 7. El nombre a se vincula a Este nuevo entero. Entonces, ahora, en lugar de apuntar a 5, ahora apunta a 7.

Volviendo a tu ejemplo:

  1. a = 1 – aquí, el nombre a está vinculado a 1
  2. b = a – y luego vinculamos el nombre b al mismo objeto al que está vinculado el nombre a (es decir, el entero 1)
  3. b = 3 – y finalmente, debido a que los enteros son inmutables, no estamos cambiando el valor del objeto real 1 a 3. En cambio, el nombre b ahora está vinculado a un objeto diferente (es decir, el entero 3). Y dado que 1 siempre será 1 (porque es inmutable), imprimir a todavía nos dará 1, porque en ninguna parte del código vinculamos a un nuevo objeto.

Como a y b apuntan a la misma lista en la memoria, modificar b es como modificar a.

Puede crear una copia de la lista usando list () :

b = lista (a)

“B = a” establece b para referirse a la misma matriz a la que se refiere a. a no _contiene_ la matriz, solo se refiere a ella. Por lo tanto, b [0] afecta la misma matriz a la que se refiere a.

En el segundo caso, ayb se establecen en valores que son lo que son, y no se refieren a ningún objeto que contenga el valor.

Cuando haces la declaración

a = [1,2,3,4]

Le dice al compilador que asocie el símbolo “a” a la lista “[1,2,3,4]”, que en realidad es solo la dirección de la lista [1,2,3,4] en la memoria.

b [0] = 3

Esta declaración va a la ubicación real de b en la memoria y sobrescribe todo lo que se indexa como “0” con un 3.

a = b

Esto no hace una nueva lista. Esto dice asociar el símbolo ‘a’ con el símbolo ‘b’.

b -> a -> lista (ubicación de memoria)

La lista está asociada con la ubicación real en la memoria donde comienza la lista, y usted realmente editó la ubicación de la memoria, no b.

b = a solo copia la referencia a la lista “a” a “b”. Esto no crea una nueva lista “b” y es solo una referencia a la lista “a”. Dos referencias apuntando a la misma lista. Si no desea cambiar los elementos en a, puede intentar b = a [:], esto copiará la lista “a” a una nueva lista “b”.

Una respuesta más pitónica: porque las listas son mutables. Si hubiera hecho una tupla aa (que es inmutable), el intento de asignar a b [0] fallaría. Puede asignar b = list (a) para que b sea una lista (mutable). Entonces funcionaría como esperaba, puede asignar 7 a b [0]. Después de eso, a es (1, 2, 3, 4) yb es [7, 2, 3, 4].