In Python, la struttura dati dict viene spesso utilizzata per memorizzare informazioni annidate. Gli sviluppatori si trovano spesso di fronte alla necessità di clonare tali strutture quando lavorano con modelli, configurazioni o trasferimento di dati tra parti dell'applicazione.
La copia standard di un dict tramite assegnazione (=) crea solo un riferimento all'oggetto originale. La copia superficiale (shallow copy) copia solo l'oggetto dict, ma non gli oggetti annidati. La copia profonda (deep copy) copia ricorsivamente tutti gli oggetti interni, prevenendo l'influenza delle modifiche in una copia sull'altra.
Per la copia superficiale si può utilizzare dict.copy() o il costruttore dict(), per la copia profonda — il modulo copy e la funzione deepcopy():
import copy d = {"a": 1, "b": {"c": 2}} shallow_d = d.copy() deep_d = copy.deepcopy(d) # Ora la modifica di shallow_d['b']['c'] influenzerà d['b']['c'] # la modifica di deep_d['b']['c'] non influenzerà il dizionario originale
Caratteristiche chiave:
Può dict.copy() copiare livelli più profondi del primo livello?
No, dict.copy() crea solo una copia superficiale. I dizionari annidati saranno comunque riferimenti agli stessi oggetti del dict originale.
Se nella struttura c'è un oggetto immutabile (ad esempio una tupla), deepcopy lo copierà profondamente?
Deepcopy copia solo gli oggetti annidati mutabili. Gli oggetti immutabili rimangono tali: tuple, stringhe e numeri non vengono copiati ricorsivamente, ma vengono semplicemente trasferiti nella copia.
Si può utilizzare la serializzazione attraverso json.loads(json.dumps(dict)) per la copia profonda?
Sì, ma con alcune limitazioni. Questo metodo funziona solo per tipi serializzabili e non è adatto se nel dizionario ci sono oggetti non serializzabili (come funzioni o classi personalizzate):
import json orig = {"a": 10, "b": [1,2,3]} copy_like_deep = json.loads(json.dumps(orig)) # Non funziona per oggetti complessi
** Caso negativo
Uno sviluppatore clona le impostazioni tramite copy(), quindi modifica un valore annidato, pensando che si tratti di due strutture indipendenti.
Vantaggi:
Facile e veloce
Svantaggi:
Le modifiche agli oggetti annidati in una copia si riflettono su tutte — bug difficili da debug.
** Caso positivo
Uno sviluppatore utilizza sempre copy.deepcopy() per le strutture annidate, anche se il dict originale sembra piatto.
Vantaggi:
Indipendenza garantita dei dati, bug ridotti al minimo
Svantaggi:
Deepcopy è più lento e consuma più memoria, a volte è eccessivo.