Diccionarios en Python: el método copy explicado
Aprende todas las formas de copiar un diccionario en Python: copy(), dict(), {**d} y deepcopy(), con ejemplos claros sobre copia superficial y profunda.
Este capítulo explica todas las formas estándar de copiar un diccionario de Python, por qué una asignación simple (=) no es una copia, y cuándo necesitas una copia profunda en lugar de una superficial.
Por qué no puedes copiar un diccionario con =
Asignar un diccionario a una nueva variable no crea una copia — crea una segunda referencia al mismo objeto. Cualquier cambio realizado a través de cualquiera de las variables afecta al mismo diccionario subyacente.
original = {'a': 1, 'b': 2}
alias = original # same object, not a copy
alias['c'] = 3
print(original) # {'a': 1, 'b': 2, 'c': 3} — original changed!Para obtener un diccionario verdaderamente independiente necesitas uno de los métodos de copia que se muestran a continuación.
Copia superficial vs. copia profunda
Antes de ver los métodos, conviene entender los dos tipos de copia:
| Tipo | Qué se copia | Mutables anidados |
|---|---|---|
| Copia superficial | Pares clave-valor del nivel superior | Las referencias se comparten — mutar en un dict afecta al otro |
| Copia profunda | Cada objeto a cada nivel | Completamente independiente — sin referencias compartidas |
Para diccionarios planos (los valores son string, números, None, boolean) una copia superficial es siempre suficiente. Para diccionarios que contienen listas, conjuntos u otros diccionarios como valores, considera una copia profunda.
Método 1: dict.copy()
El método incorporado copy() devuelve un nuevo diccionario que es una copia superficial del original. Es la opción más idiomática para diccionarios planos.
Sintaxis
new_dict = original_dict.copy()Crear una copia superficial de un diccionario en Python
Agregar o eliminar una clave en new_dict deja original_dict intacto porque la copia del nivel superior es independiente.
Actualizar claves del nivel superior en un diccionario copiado
Método 2: Constructor dict()
Pasar un diccionario existente al constructor dict() crea una copia superficial de la misma manera que copy().
original_dict = {'name': 'Alice', 'age': 30}
new_dict = dict(original_dict)
new_dict['age'] = 31
print(original_dict) # {'name': 'Alice', 'age': 30}
print(new_dict) # {'name': 'Alice', 'age': 31}dict() es útil cuando quieres ser explícito al crear un diccionario a partir de otro mapeo o cuando combinas argumentos de palabra clave con un diccionario existente:
defaults = {'color': 'blue', 'size': 'M'}
custom = dict(defaults, size='L', weight='light')
print(custom)
# {'color': 'blue', 'size': 'L', 'weight': 'light'}Método 3: Desempaquetado de diccionarios {**d}
El operador de desempaquetado ** fusiona un diccionario en un nuevo literal de diccionario. Para una copia simple se comporta de forma idéntica a copy(), pero también permite combinar varios diccionarios o sobreescribir claves individuales en una sola expresión.
original_dict = {'a': 1, 'b': 2}
new_dict = {**original_dict}
new_dict['c'] = 3
print(original_dict) # {'a': 1, 'b': 2}
print(new_dict) # {'a': 1, 'b': 2, 'c': 3}Copiar sobreescribiendo una clave
config = {'host': 'localhost', 'port': 5432, 'debug': False}
prod_config = {**config, 'host': 'db.example.com', 'debug': False}
print(prod_config)
# {'host': 'db.example.com', 'port': 5432, 'debug': False}Al igual que copy(), esto es una copia superficial — los mutables anidados siguen siendo compartidos.
Problema con la copia superficial: los mutables anidados se comparten
Los tres métodos anteriores producen copias superficiales. Cuando un valor es en sí mismo un objeto mutable (como una lista), tanto el original como la copia mantienen una referencia al mismo objeto interno.
Actualizar valores mutables dentro de un diccionario copiado
Ambos diccionarios reflejan el cambio porque new_dict['key1'] y original_dict['key1'] apuntan al mismo objeto lista. Este es el comportamiento esperado para una copia superficial — no es un error.
Método 4: copy.deepcopy() para independencia total
Cuando necesitas aislamiento completo — incluyendo listas, conjuntos y diccionarios anidados — usa copy.deepcopy() del módulo estándar copy. Copia recursivamente cada objeto de la estructura.
Copia profunda en Python
deepcopy() maneja estructuras anidadas de cualquier profundidad e incluso objetos autorreferenciales. Su contrapartida es velocidad y memoria: es más lento que una copia superficial porque debe recorrer y duplicar todo el grafo de objetos.
Elegir el método adecuado
| Situación | Método recomendado |
|---|---|
| Diccionario plano (sin mutables anidados) | dict.copy() o {**d} |
| Combinar / sobreescribir claves al copiar | {**d, key: value} o dict(d, key=value) |
| Mutables anidados, necesitas independencia total | copy.deepcopy() |
| Convertir otro mapeo en una copia de diccionario | dict(mapping) |
Resumen
- El operador
=crea un alias, no una copia. dict.copy(),dict()y{**d}producen copias superficiales — las claves del nivel superior son independientes, pero los mutables anidados se comparten.copy.deepcopy()produce una copia profunda — cada objeto a cada nivel se duplica.- Para diccionarios planos, prefiere
dict.copy()por claridad. - Usa
{**d, overrides}cuando necesites copiar y modificar en una sola expresión.
Ver también: Métodos de diccionario · Diccionarios anidados · Iterar sobre diccionarios