Il GIST da prendere è questo: trattare con liste poco profonde (senza liste secondarie, solo singoli elementi) usando "assegnazione normale" genera un "effetto collaterale" quando si crea una lista superficiale e quindi si crea una copia di questa lista usando "assegnazione normale" . Questo "effetto collaterale" si verifica quando si modifica qualsiasi elemento dell'elenco copie creato, poiché cambierà automaticamente gli stessi elementi dell'elenco originale. Questo è copy
utile quando non cambia gli elementi dell'elenco originale quando si cambiano gli elementi della copia.
D'altra parte, copy
ha anche un "effetto collaterale", quando si dispone di un elenco che contiene elenchi (elenchi secondari) e lo deepcopy
risolve. Ad esempio, se si crea un grande elenco che contiene elenchi nidificati (elenchi secondari) e si crea una copia di questo grande elenco (l'elenco originale). L '"effetto collaterale" si presenterebbe quando si modificano le liste secondarie dell'elenco copie che modifica automaticamente le liste secondarie dell'elenco grande. A volte (in alcuni progetti) vuoi mantenere la grande lista (la tua lista originale) così com'è senza modifiche, e tutto ciò che vuoi è fare una copia dei suoi elementi (sub_lists). Per questo, la tua soluzione è utilizzare deepcopy
che si occuperà di questo "effetto collaterale" e ne farà una copia senza modificare il contenuto originale.
I diversi comportamenti copy
e deep copy
operazioni riguardano solo oggetti composti (ovvero: oggetti che contengono altri oggetti come gli elenchi).
Ecco le differenze illustrate in questo semplice esempio di codice:
Primo
controlliamo come copy
si comporta (superficiale) creando un elenco originale e una copia di questo elenco:
import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)
Ora, eseguiamo alcuni print
test e vediamo come si comporta l'elenco originale rispetto al suo elenco di copie:
original_list e copy_list hanno indirizzi diversi
print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328
gli elementi di original_list e copy_list hanno gli stessi indirizzi
print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440
gli elementi secondari di original_list e copy_list hanno gli stessi indirizzi
print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x1faef08 0x1faef08
la modifica degli elementi original_list NON modifica gli elementi copy_list
original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]
la modifica degli elementi copy_list NON modifica gli elementi original_list
copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]
modifica original_list sub_elements modifica automaticamente copy_list sub_elements
original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 7]
modifica copy_list sub_elements modifica automaticamente original_list sub_elements
copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 7]
Secondo
controlliamo come deepcopy
si comporta, facendo la stessa cosa che abbiamo fatto con copy
(creando un elenco originale e una copia di questo elenco):
import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)
Ora, eseguiamo alcuni print
test e vediamo come si comporta l'elenco originale rispetto al suo elenco di copie:
import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.deepcopy(original_list)
original_list e copy_list hanno indirizzi diversi
print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328
gli elementi di original_list e copy_list hanno gli stessi indirizzi
print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440
gli elementi secondari di original_list e copy_list hanno indirizzi diversi
print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x24eef08 0x24f3300
la modifica degli elementi original_list NON modifica gli elementi copy_list
original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]
la modifica degli elementi copy_list NON modifica gli elementi original_list
copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]
la modifica di original_list sub_elements NON modifica copy_list sub_elements
original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]
la modifica di copy_list sub_elements NON modifica original_list sub_elements
copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'd'], 7]