lettura facile

Il metodo deepcopy di Python

Il metodo deepcopy() ti consente di fare una copia di oggetto iterabile (es. dizionari, liste, ecc. ) evitando di copiare i collegamenti esterni o riferimenti. La sintassi base del metodo è la seguente:

copy.deepcopy(x, memo=None, _nil=[])

  • x è l'oggetto che vuoi copiare. Può essere qualsiasi tipo di oggetto in Python, inclusi, ma non limitati a, dizionari, liste, classi personalizzate, ecc.
  • memo (opzionale) è un dizionario che viene utilizzato dalla funzione deepcopy() per evitare problemi di copia infinita in presenza di riferimenti circolari. Questo parametro è utilizzato principalmente dal meccanismo interno di deepcopy() e raramente necessita di essere specificato dall'utente.
  • _nil (opzionale) è un parametro tecnico usato internamente dalla funzione deepcopy(). Generalmente, non viene modificato o utilizzato direttamente negli script comuni.

Il metodo copia l'oggetto portando con sé i dati anziché i riferimenti.

A cosa serve? Questa funzione è essenziale quando si hai un oggetto che contiene dizionari, liste, o altri oggetti mutabili come elementi. Usare deepcopy() ti garantisce di fare una copia profonda dei dati, evitando di copiare i collegamenti esterni. In questo modo le modifiche apportate alla copia del dizionario o della lista non influenzano quello originale.

Prima di continuare vediamo di capire qual è la differenza tra una copia superficiale (shallow copy) e una copia profonda (deep copy) dei dati.

  • La copia superficiale crea una nuova istanza del dizionario, ma fa riferimento agli stessi oggetti contenuti nel dizionario o nella lista originale. Quindi, se modifichi gli oggetti interni della copia, questi cambiamenti si riflettono anche nell'originale.
  • La copia profonda crea una copia completamente nuova e indipendente dall'originale, inclusi tutti gli oggetti che contiene. Eventuali modifiche agli oggetti interni della copia non influenzano l'originale.

Ricorda che per utilizzare deepcopy devi prima importarlo dal modulo copy.

import copy

A questo punto possiamo fare qualche esempio pratico di applicazione del metodo deepcopy() con i dizionari e le liste.

Il metodo deepcopy() nei dizionari

Definisci un dizionario con qualche chiave e altrettanti valori.

dizionario_originale = {'chiave1': [1, 2, 3], 'chiave2': {'sottochiave': 4}}

Poi crea una copia profonda con il metodo deepcopy()

dizionario_copia = copy.deepcopy(dizionario_originale)

A questo punto modifica una chiave del dizionario che hai copiato in modo profondo tramite deepcopy()

Ad esempio, aggiungi il valore 4 dentro la lista associata alla chiave1.

dizionario_copia['chiave1'].append(4)

Ora visualizza il contenuto del dizionario copiato.

print("Copia:", dizionario_copia)

Il dizionario contiene il dato aggiornato.

Copia: {'chiave1': [1, 2, 3, 4], 'chiave2': {'sottochiave': 4}}

Visualizza anche il contenuto del dizionario originale.

print("Originale:", dizionario_originale)

Il contenuto del dizionario originale non è stato modificato.

Originale: {'chiave1': [1, 2, 3], 'chiave2': {'sottochiave': 4}}

Se avessi fatto una copia superficiale, la modifica si sarebbe estesa anche al dizionario originale.

Esempio di copia superficiale. Per capire la differenza, rifacciamo lo stesso esempio facendo una copia superficiale. Definisci il dizionario originale.

dizionario_originale = {'chiave1': [1, 2, 3], 'chiave2': {'sottochiave': 4}}

Poi fai una copia superficiale tramite il metodo copy

dizionario_copia_superficiale = dizionario_originale.copy()

Ora modifica un elemento della copia, aggiungi il valore 4 nella lista associata alla chiave1

dizionario_copia_superficiale['chiave1'].append(4)

A questo punto stampa il contenuto del dizionario copiato e di quello originale.

print("Copia:", dizionario_copia)
print("Originale:", dizionario_originale)

In questo caso la modifica alla lista ha influenzato anche il dizionario originale, non solo la copia superficiale.

Copia: {'chiave1': [1, 2, 3, 4], 'chiave2': {'sottochiave': 4}}
Originale: {'chiave1': [1, 2, 3, 4], 'chiave2': {'sottochiave': 4}}

Questo dovrebbe rendere molto più chiara la differenza tra una copia profonda realizzata con deepcopy e una copia superficiale ottenuta con il metodo copy.

Il metodo deepcopy() nelle liste

Immagina di avere una lista annidata, cioè una lista che contiene altre liste.

lista_originale = [1, [2, 3], [4, 5]]

In questo caso la lista originale contiene elementi sia semplici (come numeri) che complessi (altre liste).

Supponi ora di voler creare una copia di questa lista, in modo che le modifiche apportate alla copia non influenzino la lista originale.

Utilizza deepcopy() per creare una copia profonda e indipendente dalla lista originale.

lista_copiata = copy.deepcopy(lista_originale)

Ora modifica un elemento nella lista copiata.

Ad esempio, aggiungi il valore 6 alla sottolista [2,3], quella che si trova nel secondo elemento della lista copiata.

lista_copiata[1].append(6)

Infine, stampa il contenuto della lista originale e della lista copiata.

print("Lista Originale:", lista_originale)
print("Lista Copiata:", lista_copiata)

La modifica ha interessato solo la lista copiata, non ha influenzato la lista originale.

Lista Originale: [1, [2, 3], [4, 5]]
Lista Copiata: [1, [2, 3, 6], [4, 5]]

Se tu avessi fatto una copia superficiale della lista, la modifica avrebbe cambiato anche il contenuto della lista originale.

Esempio di copia superficiale. Per completezza, prova a fare la stessa cosa con una copia superficiale della lista. Ad esempio, definisci una lista.

lista_originale = [1, [2, 3], [4, 5]]

Effettua una copia superficiale della lista usando il metodo copy

lista_copiata = lista_originale.copy()

Adesso modifica un elemento della sottolista nella lista copiata. Ad esempio, aggiungi il valore 6.

lista_copiata[1].append(6)

Infine, stampa il contenuto della lista copiata e della lista originale.

print("Lista Originale:", lista_originale)
print("Lista Copiata:", lista_copiata)

In questo caso la modifica alla lista copiata ha contenuto anche quello della lista originale.

Lista Originale: [1, [2, 3, 6], [4, 5]]
Lista Copiata: [1, [2, 3, 6], [4, 5]]

Il metodo deepcopy() nelle tuple

Vediamo come applicare il metodo deepcopy a una tupla.

Ad esempio, crea una tupla con elementi immutabili e mutabili.

tupla_originale = (1, 2, 3, [4, 5])

Come puoi vedere, la tupla contiene sia elementi semplici come i numeri 1, 2, 3 che complessi come la lista [4,5].

Ora utilizza deepcopy() per creare una copia profonda della tupla

tupla_copiata = copy.deepcopy(tupla_originale)

Modifica l'elemento mutabile, la lista [4,5], nella tupla copiata, aggiungendo il valore 6.

tupla_copiata[3].append(6)

A questo punto stampa sia la tupla originale che la copia.

print("Originale:", tupla_originale)
print("Copia:", tupla_copiata)

La modifica apportata all'elemento mutabile nella tupla copiata non influisce sulla tupla originale.

Originale: (1, 2, 3, [4, 5])
Copia: (1, 2, 3, [4, 5, 6])

 

Questi esempi mostra chiaramente come deepcopy() sia efficace nel mantenere separati gli oggetti copiati dai loro originali, preservando l'integrità dei dati originali anche quando vengono effettuate modifiche profonde alla copia.

 




Se qualcosa non ti è chiaro, scrivi la tua domanda nei commenti.




FacebookTwitterLinkedinLinkedin