Copia un dizionario in Python

Rayven Esplanada 30 marzo 2021
  1. Copia un dizionario in Python: passaggio per riferimento
  2. Copia un dizionario in Python: passaggio per valore
  3. Copia superficiale del dizionario Python
Copia un dizionario in Python

Questo tutorial spiega come copiare un dizionario in Python.

Dimostreremo come copiare un dizionario in due modi: passando per valore e passando per riferimento.

Copia un dizionario in Python: passaggio per riferimento

In Python, gli oggetti non vengono copiati implicitamente. Se proviamo a copiare food in una nuova variabile meal, i valori di food verranno copiati in meal, ma lo sarà anche il riferimento di food.

meal = food

L’equazione diretta di un oggetto con un altro farà sì che il nuovo oggetto punti a quello precedente; ciò significa che le due variabili faranno riferimento allo stesso oggetto univoco.

Se aggiorniamo il valore Fruit in meal in Banana, anche il valore di Fruit in food verrà sostituito.

meal["Fruit"] = "Banana"
print(food)
print(meal)

Produzione:

{'Fruit': 'Banana', 'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod'}
{'Fruit': 'Banana', 'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod'}

Lo stesso vale se proviamo ad aggiornare una chiave nel blocco meal. Sostituiremo la chiave Fruit con Circle Fruit e copieremo il suo valore prima di estrarlo dal dizionario.

meal["Circle Fruit"] = meal.pop("Fruit")
print(food)
print(meal)

Produzione:

{'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod', 'Circle Fruit': 'Orange'}
{'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod', 'Circle Fruit': 'Orange'}

Il valore di food verrà comunque sostituito anche se non lo abbiamo modificato direttamente; questo perché il metodo che abbiamo usato per copiare food in meal passa per riferimento.

Dizionario di copia Python - Passa per riferimento

Copia un dizionario in Python: passaggio per valore

Passare per valore significa che una copia effettiva dell’oggetto verrà creata in memoria, invece di puntare la copia all’oggetto originale quando si copia un oggetto.

Se vogliamo copiare un dizionario ed evitare di fare riferimento ai valori originali, allora dovremmo trovare un modo per istanziare un nuovo oggetto nella memoria. In Python, ci sono alcune funzioni che supportano questo approccio: dict(), copy() e deepcopy().

La funzione dict() istanzia un nuovo oggetto dizionario. Se avvolgi un dizionario esistente attorno a questa funzione, verrà creata una nuova istanza dell’oggetto.

Per questo metodo, utilizzeremo lo stesso esempio dal dizionario food.

meal = dict(food)

Un altro modo per passare per valore è usare il comando copy(), che fa la stessa cosa di dict(): istanziare un nuovo oggetto nella memoria. La differenza è che copy() è una funzione incorporata degli oggetti di raccolta, inclusi i dizionari.

meal = food.copy()

Per entrambi gli scenari, modifichiamo il valore Fruit e sostituiamo la chiave Vegetable:

meal["Fruit"] = "Apple"
meal["Greens"] = meal.pop("Vegetable")
print(food)
print(meal)

Produzione:

{'Fruit': 'Orange', 'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod'} # food (original)
{'Fruit': 'Apple', 'Poultry': 'Chicken', 'Fish': 'Cod', 'Greens': 'Lettuce'} # meal (copy)

Istanziando un nuovo oggetto meal usando dict() o copy(), evitiamo di fare riferimento all’oggetto originale e di aggiornare i suoi valori se meal viene aggiornato.

Copia superficiale del dizionario Python

Il problema con dict() e copy() è che applicano solo una copia superficiale all’oggetto in uso; questo sarà un problema se il tuo dizionario ha una complessa struttura nidificata.

La copia superficiale copierà solo il primo livello nella memoria che vede perché gli oggetti annidati occupano nuovi spazi.

Dizionario di copia Python - Copia superficiale

Cambiamo l’oggetto originale in un dizionario annidato.

info = {
    "Numbers": [1, 2, 3],
    "Resident Name": "Sherlock",
    "Address": {"Street": "Baker", "Number": "221B", "City": "Miami"},
}

Dichiariamo un nuovo oggetto info2 usando copy() e dict() per copiare da info e cambiamo alcuni valori nel dizionario annidato.

info2 = info.copy()  # or dict(info)
info2["Numbers"][1] = 4
info2["Resident Name"] = "Holmes"
info2["Address"]["City"] = "Lexington"
print(info)
print(info2)

Produzione:

{'Numbers': [1, 4, 3], 'Resident Name': 'Sherlock', 'Address': {'Street': 'Baker', 'Number': '221B', 'City': 'Lexington'}}
{'Numbers': [1, 4, 3], 'Resident Name': 'Holmes', 'Address': {'Street': 'Baker', 'Number': '221B', 'City': 'Lexington'}}

I nuovi valori di Numbers e Address.City vengono aggiornati sia nella versione originale che in quella di copia. Il valore Resident Name ha aggiornato solo il blocco info2 perché abbiamo eseguito solo una copia superficiale sull’oggetto.

Copia profonda con il modulo copy in Python

La copia profonda risolve essenzialmente il problema della copia superficiale. Dopo aver copiato un oggetto, verifica la presenza di oggetti nidificati e crea in modo ricorsivo nuovi oggetti nella memoria.

In Python, possiamo ottenere una copia profonda con il modulo copy, che contiene operazioni e utilità di copia superficiale e profonda.

import copy

Useremo la funzione deepcopy() del modulo per copiare in profondità gli oggetti annidati all’interno del nostro dizionario. Useremo lo stesso blocco info di esempio sopra.

info2 = copy.deepcopy(info)
info2["Numbers"][1] = 4
info2["Resident Name"] = "Holmes"
info2["Address"]["City"] = "Lexington"
print(info)
print(info2)

Produzione:

{'Numbers': [1, 2, 3], 'Resident Name': 'Sherlock', 'Address': {'Street': 'Baker', 'Number': '221B', 'City': 'Miami'}}
{'Numbers': [1, 4, 3], 'Resident Name': 'Holmes', 'Address': {'Street': 'Baker', 'Number': '221B', 'City': 'Lexington'}}

Ora, il dizionario originale info rimane invariato, anche con le molteplici modifiche in info2, inclusi gli oggetti annidati.

In sintesi, ci sono molti modi per copiare un dizionario in Python, ma l’output non sarà lo stesso per tutti. Assegnare direttamente un dizionario con = lo passerà per riferimento, puntando all’oggetto originale.

Funzioni di copia superficiale come dict() e copy() risolveranno il problema solo per dizionari non annidati.
Il modo migliore per copiare un dizionario, considerando i dizionari annidati, è usare la funzione deepcopy() fornita dal modulo copy.

Rayven Esplanada avatar Rayven Esplanada avatar

Skilled in Python, Java, Spring Boot, AngularJS, and Agile Methodologies. Strong engineering professional with a passion for development and always seeking opportunities for personal and career growth. A Technical Writer writing about comprehensive how-to articles, environment set-ups, and technical walkthroughs. Specializes in writing Python, Java, Spring, and SQL articles.

LinkedIn

Articolo correlato - Python Dictionary