Copias profundas vs superficiales en Python

En este tutorial, vamos a discutir las copias superficiales frente a las copias profundas con la ayuda de ejemplos en Python. Cubriremos la definición de un profundo y superficial ...

Introducción

En este tutorial, vamos a discutir las copias superficiales frente a las copias profundas con la ayuda de ejemplos en Python. Cubriremos la definición de una copia profunda y superficial, junto con su implementación en el lenguaje Python para evaluar las diferencias principales entre los dos tipos de copias.

En muchos de los programas que escribimos, sin importar cuán básicos sean, terminamos necesitando copiar una lista o un objeto por una de muchas razones, como la eficiencia computacional. Hay dos formas de hacerlo, ya sea haciendo una copia profunda o una copia superficial. Antes de discutir las diferencias entre los dos, primero comprendamos qué son exactamente las copias profundas y superficiales.

Copias profundas en Python

Una copia profunda hace una copia nueva y separada de un objeto o lista completa con su propia dirección de memoria única. Lo que esto significa es que cualquier cambio que realice en la nueva copia del objeto/lista no se reflejará en el original. Este proceso ocurre creando primero una nueva lista u objeto, seguido de la copia recursiva de los elementos del original al nuevo.

En pocas palabras, ambos objetos son completamente independientes entre sí. Esto es similar al concepto de pasar por valor en lenguajes como C++, Java y C#.

Ejemplo de copia profunda

Para implementar el concepto de copias profundas en Python, usaremos el módulo Copiar.

Digamos que tenemos una lista de listas llamada result_A, que contiene las calificaciones del estudiante A en 3 materias durante los primeros dos años de escuela, y también deseamos crear una lista de resultados exactamente similar para el estudiante B. Intentaremos hacer una copia profunda de la lista result_A, y luego haremos algunos cambios en esa copia profunda para mostrar las calificaciones del estudiante B.

Ejemplo 1:

1
2
3
4
5
6
7
8
# Program 1 - Deep Copy
import copy

result_A = [[90, 85, 82], [72, 88, 90]] # Student A grades
result_B = copy.deepcopy(result_A) # Student B grades (copied from A)

print(result_A)
print(result_B)

En el script anterior, usamos el método deepcopy del módulo copy para copiar la lista result_A a result_B. A continuación, imprimimos el contenido de ambas listas en la pantalla.

Producción:

1
2
[[90, 85, 82], [72, 88, 90]]
[[90, 85, 82], [72, 88, 90]]

Como puede ver, las listas son idénticas. Más adelante en este artículo veremos cómo esto es diferente de las copias superficiales.

Copias superficiales en Python

Una copia superficial también crea un objeto o una lista de objetos nuevos por separado, pero en lugar de copiar los elementos secundarios en el objeto nuevo, simplemente copia las referencias a sus direcciones de memoria. Por lo tanto, si realiza un cambio en el objeto original, se reflejará en el objeto copiado y viceversa. Para decirlo brevemente, ambas copias dependen una de la otra. Esto es similar al concepto de pasar por referencia en lenguajes de programación como C++, C# y Java.

Ejemplo de copia superficial

Para implementar esto en Python, usaremos el módulo “copiar” nuevamente, pero esta vez llamaremos a su función “copiar”.

Usemos la misma lista de ejemplo para el ejemplo de copia superficial también.

Ejemplo 2:

1
2
3
4
5
6
7
8
# Program 2 - Shallow Copy
import copy

result_A = [[90, 85, 82], [72, 88, 90]]
result_B = copy.copy(result_A)

print(result_A)
print(result_B)

En el script anterior, usamos el método copiar del módulo copiar para hacer una copia superficial de la lista resultado_A que llamamos resultado_B. A continuación, el contenido de ambas listas se imprimió en la consola.

Producción:

1
2
[[90, 85, 82], [72, 88, 90]]
[[90, 85, 82], [72, 88, 90]]

Nuevamente, las listas son las mismas, como se esperaba. A continuación, explicaremos la diferencia entre los resultados que obtenemos de las funciones copy y deepcopy.

Diferencia entre copias profundas y superficiales

Ahora que hemos discutido qué son las copias superficiales y profundas y por qué creamos copias, es hora de hablar sobre la diferencia entre ellas. Esencialmente, solo hay dos diferencias principales y están vinculadas entre sí:

  1. La copia profunda almacena copias de los valores de un objeto, mientras que las historias de copia superficial referencias a la dirección de memoria original
  2. La copia profunda no refleja los cambios realizados en el objeto nuevo/copiado en el objeto original; mientras que la copia superficial sí

Antes de pasar a la implementación, me gustaría que imagine este escenario. Digamos que dos personas desean compartir una bebida; tienen dos vasos vacíos y dos pajitas. Pueden compartir esta bebida de dos maneras:

  1. Ponga la bebida en un vaso y ponga ambas pajitas en ese vaso para compartir
  2. Pon la bebida en ambos vasos y pon una pajilla en cada vaso.

El primer escenario es el de una copia superficial. Ambas variables/instancias apuntan/utilizan la misma ubicación de memoria para sus operaciones. El segundo escenario es el de una copia profunda. Ambas variables/instancias apuntan a/utilizan dos ubicaciones de memoria diferentes para sus operaciones.

Ejemplo de comparación

Para aclarar la diferencia, usemos esta información en nuestros dos ejemplos anteriores, comenzando con Ejemplo 1.

Arriba, creamos la lista result_A e hicimos una copia profunda llamada result_B. Intentemos cambiar el contenido en result_B y veamos si tiene algún efecto en el contenido de result_A.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import copy

result_A = [[90, 85, 82], [72, 88, 90]] # Student A grades
result_B = copy.deepcopy(result_A) # Student B grades (copied from A)

# Change first year and first subject's marks to 30
result_B[0][0] = 30

print("Original List: ")
print(result_A)
print("Deep Copy:")
print(result_B)

Producción:

1
2
3
4
Original List:
[[90, 85, 82], [72, 88, 90]]
Deep Copy:
[[30, 85, 82], [72, 88, 90]]

El resultado esperado es que la lista original permanezca sin cambios. Y como puede ver, los cambios en la copia profunda no afectaron a la lista original.

Ahora, intentemos lo mismo con Ejemplo 2 - Copia superficial.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import copy

result_A = [[90, 85, 82], [72, 88, 90]] # Student A grades
result_B = copy.copy(result_A) # Student B grades (copied from A)

# Change first year and first subject's marks to 30
result_B[0][0] = 30

print("Original List: ")
print(result_A)
print("Shallow Copy:")
print(result_B)

Producción:

1
2
3
4
Original List:
[[30, 85, 82], [72, 88, 90]]
Shallow Copy:
[[30, 85, 82], [72, 88, 90]]

Aquí, el resultado esperado es que tanto la lista original como la lista copiada se modifican después del único cambio. Y como puede ver, al hacer el cambio en la copia superficial, ese cambio también se reflejó en la lista original.

Conclusión

En esta publicación, hablamos sobre qué es una copia superficial y profunda y cómo podemos hacerlas en lenguaje Python usando el módulo 'copiar'. Usamos dos de sus funciones, es decir, copiar y deepcopy para hacer copias superficiales y profundas, respectivamente. Además, discutimos las dos diferencias principales entre una copia superficial y profunda, y también implementamos una copia superficial y profunda en python para comprender mejor esas diferencias.

Licensed under CC BY-NC-SA 4.0