in

python: lista de cambios inesperados después de la asignación. ¿Por qué es esto y cómo puedo prevenirlo?

apple touch icon@2

Comencemos desde el principio y exploremos esta pregunta.

Supongamos que tiene dos listas:

list_1 = ['01', '98']
list_2 = [['01', '98']]

Y tenemos que copiar ambas listas, ahora comenzando desde la primera lista:

Así que primero intentemos configurando la variable copy a nuestra lista original, list_1:

copy = list_1

Ahora, si está pensando copiar, copió el list_1, entonces estás equivocado. los id La función puede mostrarnos si dos variables pueden apuntar al mismo objeto. Intentemos esto:

print(id(copy))
print(id(list_1))

La salida es:

4329485320
4329485320

Ambas variables son exactamente el mismo argumento. ¿Estás sorprendido?

Entonces, como sabemos, Python no almacena nada en una variable, las variables solo hacen referencia al objeto y el objeto almacena el valor. Aquí el objeto es un list pero creamos dos referencias a ese mismo objeto con dos nombres de variable diferentes. Esto significa que ambas variables apuntan al mismo objeto, solo que con nombres diferentes.

Cuando tu lo hagas copy = list_1, en realidad está haciendo:

Ingrese la descripción de la imagen aquí

Aquí en la imagen list_1 y Copiar son dos nombres de variable, pero el objeto es el mismo para ambas variables, que es list.

Entonces, si intenta modificar la lista copiada, también modificará la lista original porque la lista es solo una allí, modificará esa lista sin importar lo que haga de la lista copiada o de la lista original:

copy[0] = "modify"

print(copy)
print(list_1)

Producción:

['modify', '98']
['modify', '98']

Entonces modificó la lista original:

Ahora pasemos a un método Pythonic para copiar listas.

copy_1 = list_1[:]

Este método soluciona el primer problema que tuvimos:

print(id(copy_1))
print(id(list_1))

4338792136
4338791432

Entonces, como podemos ver que nuestra lista tiene una identificación diferente, significa que ambas variables apuntan a objetos diferentes. Entonces, lo que realmente está sucediendo aquí es:

Ingrese la descripción de la imagen aquí

Ahora intentemos modificar la lista y veamos si aún nos enfrentamos al problema anterior:

copy_1[0] = "modify"

print(list_1)
print(copy_1)

La salida es:

['01', '98']
['modify', '98']

Como puede ver, solo modificó la lista copiada. Eso significa que funcionó.

¿Crees que hemos terminado? No. Intentemos copiar nuestra lista anidada.

copy_2 = list_2[:]

list_2 debe hacer referencia a otro objeto que es copia de list_2. Vamos a revisar:

print(id((list_2)), id(copy_2))

Obtenemos la salida:

4330403592 4330403528

Ahora podemos asumir que ambas listas apuntan a un objeto diferente, así que ahora intentemos modificarlo y veamos que está dando lo que queremos:

copy_2[0][1] = "modify"

print(list_2, copy_2)

Esto nos da la salida:

[['01', 'modify']] [['01', 'modify']]

Esto puede parecer un poco confuso, porque el mismo método que usamos anteriormente funcionó. Tratemos de entender esto.

Cuando tu lo hagas:

copy_2 = list_2[:]

Solo está copiando la lista externa, no la lista interna. Podemos usar el id función una vez más para comprobar esto.

print(id(copy_2[0]))
print(id(list_2[0]))

La salida es:

4329485832
4329485832

Cuando lo hacemos copy_2 = list_2[:], esto pasa:

Ingrese la descripción de la imagen aquí

Crea la copia de la lista, pero solo la copia de la lista externa, no la copia de la lista anidada. La lista anidada es la misma para ambas variables, por lo que si intenta modificar la lista anidada, también modificará la lista original, ya que el objeto de la lista anidada es el mismo para ambas listas.

¿Cuál es la solución? La solucion es la deepcopy función.

from copy import deepcopy
deep = deepcopy(list_2)

Revisemos esto:

print(id((list_2)), id(deep))

4322146056 4322148040

Ambas listas externas tienen diferentes ID. Probemos esto en las listas anidadas internas.

print(id(deep[0]))
print(id(list_2[0]))

La salida es:

4322145992
4322145800

Como puede ver, ambos ID son diferentes, lo que significa que podemos suponer que ambas listas anidadas apuntan a un objeto diferente ahora.

Esto significa que cuando lo hagas deep = deepcopy(list_2) lo que realmente sucede:

Ingrese la descripción de la imagen aquí

Ambas listas anidadas apuntan a un objeto diferente y ahora tienen una copia separada de la lista anidada.

Ahora intentemos modificar la lista anidada y ver si resolvió el problema anterior o no:

deep[0][1] = "modify"
print(list_2, deep)

Produce:

[['01', '98']] [['01', 'modify']]

Como puede ver, no modificó la lista anidada original, solo modificó la lista copiada.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scala – Operadores

iH2xvzQ9H9aBTgrn7WyftC 1200 80

The Last of Us Part 2 New Game Plus Mode: lo que te ofrece y cómo desbloquearlo