Cómo copiar un diccionario en Python

Rayven Esplanada 17 diciembre 2020
  1. Copiar un diccionario en Python: Pasando por referencia
  2. Copiar un diccionario en Python: Pasando por el valor
  3. Copia superficial del Diccionario Python
Cómo copiar un diccionario en Python

Este tutorial explica cómo se puede copiar un diccionario en Python.

Vamos a demostrar cómo copiar un diccionario de dos maneras: pasando por valor y pasando por referencia.

Copiar un diccionario en Python: Pasando por referencia

En Python, los objetos no se copian implícitamente. Si intentamos copiar food a una nueva variable meal, los valores de food se copiarán en meal, pero también lo hará la referencia de food.

meal = food

Al equiparar directamente un objeto con otro, el nuevo objeto apuntará al anterior; esto significa que las dos variables harán referencia al mismo objeto único.

Si actualizamos el valor de Fruit en meal a Banana, el valor de Fruit en food también será reemplazado.

meal["Fruit"] = "Banana"
print(food)
print(meal)

Resultado:

{'Fruit': 'Banana', 'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod'}
{'Fruit': 'Banana', 'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod'}

Lo mismo ocurre si intentamos actualizar una clave en el bloque meal. Reemplazaremos la clave Fruit por Circle Fruit y copiaremos su valor antes de sacarla del diccionario.

meal["Circle Fruit"] = meal.pop("Fruit")
print(food)
print(meal)

Resultado:

{'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod', 'Circle Fruit': 'Orange'}
{'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod', 'Circle Fruit': 'Orange'}

El valor de food será reemplazado aunque no lo hayamos modificado directamente; esto se debe a que el método que usamos para copiar food a meal está pasando por referencia.

Copia del diccionario en Python - Pasar por referencia

Copiar un diccionario en Python: Pasando por el valor

Pasar por valor significa que se creará una copia real del objeto en la memoria, en lugar de apuntar la copia al objeto original al copiar un objeto.

Si queremos copiar un diccionario y evitar la referencia a los valores originales, entonces debemos encontrar una manera de instanciar un nuevo objeto en la memoria. En Python, hay unas pocas funciones que apoyan este enfoque: dict(), copy(), y deepcopy().

La función dict() instanciar un nuevo objeto del diccionario. Si envuelve un diccionario existente alrededor de esta función, se creará una nueva instancia del objeto.

Para este método, vamos a usar el mismo ejemplo del diccionario food.

meal = dict(food)

Otra forma de pasar el valor es usando el comando copy(), que hace lo mismo que dict(): instanciar un nuevo objeto en la memoria. La diferencia es que copy() es una función incorporada de los objetos de la colección, incluyendo los diccionarios.

meal = food.copy()

Para ambos escenarios, modifiquemos el valor de Fruit y reemplacemos la tecla Vegetable:

meal["Fruit"] = "Apple"
meal["Greens"] = meal.pop("Vegetable")
print(food)
print(meal)

Resultado:

{'Fruit': 'Orange', 'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod'} # food (original)
{'Fruit': 'Apple', 'Poultry': 'Chicken', 'Fish': 'Cod', 'Greens': 'Lettuce'} # meal (copy)

Al instanciar un nuevo objeto meal usando dict() o copy(), evitamos referenciar el objeto original y actualizar sus valores si meal es actualizado.

Copia superficial del Diccionario Python

El problema con dict() y copy() es que sólo aplican una copia superficial al objeto que se está usando; esto será un problema si tu diccionario tiene una estructura anidada compleja.

El copiado superficial sólo copiará la primera capa en la memoria que ve porque los objetos anidados ocupan nuevos espacios.

Diccionario de copia en Python - Copia superficial

Cambiemos el objeto original por un diccionario anidado.

info = {
    "Numbers": [1, 2, 3],
    "Resident Name": "Sherlock",
    "Address": {"Street": "Baker", "Number": "221B", "City": "Miami"},
}

Declaremos un nuevo objeto info2 usando copy() y dict() para copiar de info y cambiar algunos valores en el diccionario anidado.

info2 = info.copy()  # or dict(info)
info2["Numbers"][1] = 4
info2["Resident Name"] = "Holmes"
info2["Address"]["City"] = "Lexington"
print(info)
print(info2)

Resultado:

{'Numbers': [1, 4, 3], 'Resident Name': 'Sherlock', 'Address': {'Street': 'Baker', 'Number': '221B', 'City': 'Lexington'}}
{'Numbers': [1, 4, 3], 'Resident Name': 'Holmes', 'Address': {'Street': 'Baker', 'Number': '221B', 'City': 'Lexington'}}

Los nuevos valores de Numbers y Address.City se actualizan tanto en la versión original como en la copia. El valor Resident Name sólo actualizó el bloque info2 porque sólo hicimos una copia superficial del objeto.

Copia profunda con el módulo de copy en Python

La copia profunda esencialmente arregla el problema de la copia superficial. Al copiar un objeto, busca objetos anidados y crea recursivamente nuevos objetos en la memoria.

En Python, podemos lograr un copiado profundo con el módulo copy, que contiene operaciones y utilidades de copiado superficial y profundo.

import copy

Usaremos la función deepcopy() del módulo para copiar en profundidad los objetos anidados dentro de nuestro diccionario. Usaremos el mismo bloque info de ejemplo de arriba.

info2 = copy.deepcopy(info)
info2["Numbers"][1] = 4
info2["Resident Name"] = "Holmes"
info2["Address"]["City"] = "Lexington"
print(info)
print(info2)

Resultado:

{'Numbers': [1, 2, 3], 'Resident Name': 'Sherlock', 'Address': {'Street': 'Baker', 'Number': '221B', 'City': 'Miami'}}
{'Numbers': [1, 4, 3], 'Resident Name': 'Holmes', 'Address': {'Street': 'Baker', 'Number': '221B', 'City': 'Lexington'}}

Ahora, el diccionario original info permanece sin cambios, incluso con los múltiples cambios en info2, incluyendo los objetos anidados.

En resumen, hay muchas maneras de copiar un diccionario en Python, pero la salida no será la misma para todos. Asignar directamente un diccionario con = lo pasará por referencia, apuntando al objeto original.

Las funciones de copia superficial como dict() y copy() resolverán ese problema sólo para los diccionarios no anidados.
La mejor manera de copiar un diccionario, considerando los diccionarios anidados, es usar la función deepcopy() proporcionada por el módulo copy.

Rayven Esplanada avatar Rayven Esplanada avatar

Skilled in Python, Java, Spring Boot, AngularJS, and Agile Methodologies. Strong engineering professional with a passion for development and always seeking opportunities for personal and career growth. A Technical Writer writing about comprehensive how-to articles, environment set-ups, and technical walkthroughs. Specializes in writing Python, Java, Spring, and SQL articles.

LinkedIn

Artículo relacionado - Python Dictionary