
Mario Andrés Castro Martínez
PreguntaSe podría decir que en Python y con las listas, al copiar una lista en otra variable, esta ultima se crea por referencia a la primera y no por valor??

Mario Andrés Castro Martínez
Gracias por las respuestas. Junto con la clase me hicieron recordar conceptos que hace mucho tiempo no manejaba de la programación estructurada y me tocó desempolvar, por ejemplo, en el lenguaje de programación C cuando se hace el llamado a una función y se le envían argumentos, dichos argumentos son copiados en los parámetros de la función; lo cual quiere decir que por cada argumento transferido existe una copia almacenada en el parámetro correspondiente. A este esquema de copia de valores se le conoce en el argot computacional como parámetros por valor. Los parámetros por valor son el esquema estándar de C, es decir, es el que se utiliza normalmente si no se especifica otra cosa; sin embargo, existe otro enfoque para el envío de argumentos y su respectiva recepción como parámetros. En dicho enfoque, no hay una copia de valores sino una referencia a los valores originales, y la forma de implementarlo es a través de apuntadores. Cuando se utiliza dicho esquema se habla de parámetros por referencia.
Ahora, investigando un poco mas me encuentro con que en Python, dependiendo del tipo de dato que enviemos a la función, podemos diferenciar los dos comportamientos, por lo que los tipos simples se pasan por valor (Enteros, flotantes, cadenas, lógicos..) creándose una copia local de la variable dentro de la función y los tipos compuestos se pasan por referencia (Listas, diccionarios, conjuntos...) manejándose directamente la variable, los cambios realizados dentro de la función le afectarán también fuera.
++Ejemplo de paso por valor++ Como ya sabemos los números se pasan por valor y crean una copia dentro de la función, por eso no les afecta externamente lo que hagamos con ellos:
def doblar_valor(numero): numero *= 2 n = 10 doblar_valor(n) print(n)
++Ejemplo de paso por referencia++ Sin embargo las listas u otras colecciones, al ser tipos compuestos se pasan por referencia, y si las modificamos dentro de la función estaremos modificándolas también fuera:
def doblar_valores(numeros): for i,n in enumerate(numeros): numeros[i] *= 2 ns = [10,50,100] doblar_valores(ns) print(ns)
Para modificar los tipos simples podemos devolverlos modificados y reasignarlos:
def doblar_valor(numero): return numero * 2 n = 10 n = doblar_valor(n) print(n)
Y en el caso de los tipos compuestos, podemos evitar la modificación enviando una copia:
def doblar_valores(numeros): for i,n in enumerate(numeros): numeros[i] *= 2 ns = [10,50,100] doblar_valores(ns[:]) # Una copia al vuelo de una lista con [:] print(ns)

Bayron Danilo Ortiz Foronda
Hola @mario-castro421 así es.
Lo que debes saber es que en Python todo es un objeto. En el caso de las listas estas son mutables, quiere decir que una vez esta en memoria, ese objeto puede ser modificado, lo contrario que sucede con aquellos tipos de datos conocidos como literales (strings, int, float, booleans) que son inmutables.
Creo que con esta imagen se entiende un poco mejor:
En este caso en la cajita hay un literal, un tipo de dato entero (int) que es 7, pero imagina que simplemente es una lista. Sí tienes la variable a en la cual asignas la lista originalmente:
a = [1, 2, 3]
pero luego asignas ++a++ a la variable b,
a = [1, 2, 3] b = a
lo que hace Python implícitamente es apuntar b a la lista que esta almacenada en memoria y que fue asignada inicialmente a la variable a. Es como tener dos nombres que apuntan al mismo objeto en memoria. Sí simplemente cambiarás el valor de a por otra cosa, aún b tendría el valor que antes tenía a, que por supuesto es la lista.
>> a = [1,2,3] >> b = a >> a [1, 2, 3] >> b [1, 2, 3] >> a = 'Platzi' >> b [1, 2, 3]
Sí finalmente asignas otro valor a la variable b, entonces ya no habría ningún apuntador hacia esa lista en memoria y Python se encargaría de limpiar ese objeto de memoria con el recolector de basura (Garbage Collector).
Un truco, sí lo que deseas es copiar una lista de una variable a otra, pero generando un objeto independiente en memoria puedes usar:
>> a = [1, 2, 3] >> b = a[:] # Aquí ocurre la magia >> a [1, 2, 3] >> b [1, 2, 3] # Eliminamos elemento de a >> a.pop() >> a [1, 2] >> b [1, 2, 3]
Si te das cuenta, se quitó un elemento de la lista a, pero no afecta en ningún momento a la lista b, ya que al usar [:] cuando asignas una lista a otra, únicamente copias el contenido de la misma pero instanciando un nuevo objeto en memoria. Espero haya sido de utilidad.
Un saludo!

Daniel Adolfo Ordoñez Rubio
Hola, Mario :) Sí, tu nueva variable comparte la referencia de la primera. Pero si quieres copiar por valor, existe el método copy para objetos (diccionarios), y con las listas puedes usar [:]. Puedes ver la documentación aquí :D