Ver Mensaje Individual
  #3 (permalink)  
Antiguo 13/09/2014, 12:30
Avatar de razpeitia
razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 8 meses
Puntos: 1360
Respuesta: ¿Que utilidad tiene el método copy en listas?

Esto es muy simple una vez que entiendes el concepto de inmutabilidad.

Definición:
Cita:
Iniciado por Wikipedia
un «objeto inmutable» es un objeto cuyo estado no puede ser modificado una vez creado.
Algunos puntos a tener en cuenta:
1. En python todo es un objeto.
2. En python puedes clasificar cualquier objeto como inmutable o mutable.

Ejemplos de objetos mutables:
Listas, Diccionarios, Sets

Ejemplos de objetos inmutables:
Enteros, Flotantes, Cadenas, Tuplas, Frozensets

Mas ejemplos de inmutabilidad.
Código Python:
Ver original
  1. my_str = " ola mundo"
  2. my_str[0] = "H"
  3. # TypeError: 'str' object does not support item assignment
Como puedes ver, esto arrojara una excepción de tipo TypeError. Por que como dije arriba las cadenas son inmutables.

Código Python:
Ver original
  1. my_list = [0, 2, 3]
  2. my_list[0] = 1
Y aquí no hay ningún error. Y funciona porque nuestro objeto es mutable. Y como puedes ver, paso de tener [0, 2, 3] a tener [1, 2, 3].

¿Bueno y que tiene que ver esto con deep copy o swallow copy?
Primero vamos a ver que pasa, si no aplicamos una copia.

Código Python:
Ver original
  1. a = [1, 2, 3]
  2. print a # [1, 2, 3]
  3. b = a # Esto es una referencia a la lista a, no es una copia
  4. del b[0]
  5. print a # [2, 3] modifico nuestra lista a
  6. print b # [2, 3]

¿Como puedo evitar esto si no existiera un método copy?
Fácil creas una copia manualmente.
Código Python:
Ver original
  1. def copy(some_list):
  2.     copy_list = []
  3.     for item in some_list:
  4.         copy_list.append(item)
  5.     return copy_list
  6.  
  7. a = [1, 2, 3]
  8. b = copy(a)
  9. del b[0]
  10. print a # [1, 2, 3]
  11. print b # [2, 3]
Como puedes ver es perfectamente y crea una copia. Pero esto es un swallow copy.

¿Pero que tal si tengo objetos inmutables anidados?
Código Python:
Ver original
  1. a = [[1, 2], [3, 4]]
  2. b = copy(a)
  3. del b[0]
  4. print a # [[1, 2], [3, 4]]
  5. print b # [[3, 4]]
  6. # Funciona perfecto
  7.  
  8. del b[0][0]
  9. print a # [[1, 2], [4]]
  10. print b # [[4]]
  11. # WTF!
Ok, ¿Que paso aquí?
Es bastante fácil, cuando creo una copia de la lista, asumo que todos los objetos de la lista son inmutables. Cosa que en la vida real no es así.

Para evitar esto, existe algo llamado deep copy. Que hará una copia, no importa los niveles de anidamiento que tengas.

Mas información al respecto, puedes leer la documentación. https://docs.python.org/2/library/copy.html