Copia superficiale (shallow copy) crea un nuovo oggetto di primo livello, ma gli oggetti annidati (elementi delle liste, dizionari annidati, ecc.) condividono la memoria con l'originale. Copia profonda (deep copy) copia ricorsivamente tutti i livelli degli oggetti.
Può essere utilizzato tramite il modulo copy:
import copy original = [[1, 2], [3, 4]] shallow = copy.copy(original) deep = copy.deepcopy(original) shallow[0][0] = 99 # Cambia sia original che shallow print(original) # [[99, 2], [3, 4]] # Ora con deep original = [[1, 2], [3, 4]] deep = copy.deepcopy(original) deep[0][0] = 99 print(original) # [[1, 2], [3, 4]]
copy.copy(obj): copia solo "il wrapper"copy.deepcopy(obj): copia completamente in modo ricorsivoCosa accade quando si copia una tupla che contiene oggetti mutabili?
tuple è immutabile, ma i suoi elementi possono essere mutabili (ad esempio, una lista). Shallow copy e deep copy differiscono:
import copy t = ([1, 2], [3, 4]) shallow = copy.copy(t) deep = copy.deepcopy(t) shallow[0][0] = 99 print(t) # ([99, 2], [3, 4]) # Con deep copy: t = ([1, 2], [3, 4]) deep = copy.deepcopy(t) deep[0][0] = 88 print(t) # ([1, 2], [3, 4])
Storia
In un'applicazione per l'elaborazione di documenti, i dati erano memorizzati in un elenco all'interno di un dizionario. Durante la copia degli oggetti usando copy.copy, gli elementi annidati venivano casualmente modificati durante la modifica del nuovo oggetto. Di conseguenza, i dati originali sono stati modificati in altre parti del sistema! È avvenuta una corruzione dei dati. L'errore è stato corretto solo sostituendo con deepcopy.
Storia
In un progetto di apprendimento automatico, durante il salvataggio dei iperparametri dei modelli, si copiavano le liste di configurazione attraverso l'assegnazione standard e shallow copy, dopo di che diversi esperimenti cambiavano i propri parametri reciprocamente. La fonte del bug è stata trovata dopo una diagnosi del comportamento della copia delle liste annidate tramite deepcopy.
Storia
In un software finanziario, deep copy è stato applicato accidentalmente a un oggetto che include un file aperto (handle), il che ha causato TypeError: cannot pickle '_io.TextIOWrapper' object — perché copy.deepcopy sotto il cofano utilizza pickle. È stato corretto tramite una gestione esplicita di tali campi o chiamando shallow copy.