Dizionari Python: Il Metodo Copy Spiegato
Scopri tutti i modi per copiare un dizionario Python — copy(), dict(), {**d} e deepcopy() — con esempi chiari su shallow e deep copy.
Questo capitolo illustra ogni modo standard per copiare un dizionario Python, spiega perché una semplice assegnazione (=) non equivale a una copia, e quando è necessaria una deep copy al posto di una shallow copy.
Perché Non Puoi Copiare un Dizionario con =
Assegnare un dizionario a una nuova variabile non crea una copia — crea un secondo riferimento allo stesso oggetto. Qualsiasi modifica effettuata tramite una delle due variabili influisce sullo stesso dizionario sottostante.
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!Per ottenere un dizionario genuinamente indipendente è necessario uno dei metodi di copia mostrati di seguito.
Shallow Copy e Deep Copy
Prima di esaminare i metodi, è utile capire i due tipi di copia:
| Tipo | Cosa viene copiato | Oggetti mutabili annidati |
|---|---|---|
| Shallow copy | Coppie chiave-valore di primo livello | I riferimenti sono condivisi — una modifica in un dizionario influisce sull'altro |
| Deep copy | Ogni oggetto a ogni profondità | Completamente indipendente — nessun riferimento condiviso |
Per dizionari piatti (i valori sono string, numeri, None, boolean) una shallow copy è sempre sufficiente. Per dizionari che contengono liste, set o altri dizionari come valori, considera una deep copy.
Metodo 1: dict.copy()
Il metodo integrato copy() restituisce un nuovo dizionario che è una shallow copy dell'originale. È la scelta più idiomatica per i dizionari piatti.
Sintassi
new_dict = original_dict.copy()Eseguire una shallow copy di un dizionario in Python
Aggiungere o rimuovere una chiave in new_dict lascia original_dict invariato, perché la copia di primo livello è indipendente.
Aggiornare le chiavi di primo livello in un dizionario copiato
Metodo 2: Il Costruttore dict()
Passare un dizionario esistente al costruttore dict() crea una shallow copy nello stesso modo di 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() è utile quando si vuole essere espliciti nel creare un dizionario da un altro mapping, o quando si combinano argomenti keyword con un dizionario esistente:
defaults = {'color': 'blue', 'size': 'M'}
custom = dict(defaults, size='L', weight='light')
print(custom)
# {'color': 'blue', 'size': 'L', 'weight': 'light'}Metodo 3: Unpacking del Dizionario {**d}
L'operatore di unpacking ** unisce un dizionario in un nuovo dizionario letterale. Per una semplice copia si comporta in modo identico a copy(), ma permette anche di unire più dizionari o sovrascrivere singole chiavi in un'unica espressione.
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}Copiare sovrascrivendo una chiave
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}Come copy(), questa è una shallow copy — gli oggetti mutabili annidati sono ancora condivisi.
Attenzione alla Shallow Copy: Gli Oggetti Mutabili Annidati Sono Condivisi
Tutti e tre i metodi precedenti producono shallow copy. Quando un valore è esso stesso un oggetto mutabile (come una lista), sia l'originale che la copia mantengono un riferimento allo stesso oggetto interno.
Aggiornare valori mutabili all'interno di un dizionario copiato
Entrambi i dizionari riflettono la modifica perché new_dict['key1'] e original_dict['key1'] puntano allo stesso oggetto lista. Questo è il comportamento atteso per una shallow copy — non è un bug.
Metodo 4: copy.deepcopy() per la Piena Indipendenza
Quando hai bisogno di un isolamento completo — incluse liste, set e dizionari annidati — usa copy.deepcopy() dal modulo copy della libreria standard. Copia ricorsivamente ogni oggetto nella struttura.
Deep copy in Python
deepcopy() gestisce strutture annidate arbitrariamente profonde e persino oggetti autoreferenziali. Il compromesso è velocità e memoria: è più lenta di una shallow copy perché deve attraversare e duplicare l'intero grafo degli oggetti.
Scegliere il Metodo Giusto
| Situazione | Metodo consigliato |
|---|---|
| Dizionario piatto (nessun oggetto mutabile annidato) | dict.copy() o {**d} |
| Unire / sovrascrivere chiavi durante la copia | {**d, key: value} o dict(d, key=value) |
| Oggetti mutabili annidati, serve piena indipendenza | copy.deepcopy() |
| Convertire un altro mapping in una copia dizionario | dict(mapping) |
Riepilogo
- L'operatore
=crea un alias, non una copia. dict.copy(),dict()e{**d}producono tutti shallow copy — le chiavi di primo livello sono indipendenti ma gli oggetti mutabili annidati sono condivisi.copy.deepcopy()produce una deep copy — ogni oggetto a ogni profondità viene duplicato.- Per i dizionari piatti, preferisci
dict.copy()per chiarezza. - Usa
{**d, overrides}quando hai bisogno di copiare e modificare in un'unica espressione.
Vedi anche: Metodi dei Dizionari · Dizionari Annidati · Iterare sui Dizionari