ProgrammazioneData Engineer

Spiega la differenza tra shallow copy (copia superficiale) e deep copy (copia profonda), e il comportamento di copy.copy e copy.deepcopy nella copia di oggetti complessi. Fai un esempio in cui una comprensione errata ha portato a un bug.

Supera i colloqui con l'assistente IA Hintsage

Risposta.

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]]

Caratteristiche:

  • copy.copy(obj): copia solo "il wrapper"
  • copy.deepcopy(obj): copia completamente in modo ricorsivo
  • Alcuni oggetti (ad esempio, file aperti, socket) non vengono copiati da deep copy (eccezione)

Domanda trabocchetto.

Cosa accade quando si copia una tupla che contiene oggetti mutabili?

Risposta con esempio:

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])

Esempi di errori reali a causa della mancanza di conoscenza delle complessità dell'argomento


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.