Copiare le Liste
Scopri tutti i modi per copiare una lista Python: trappola dell'assegnazione, slicing, copy(), list() e deepcopy() — con esempi eseguibili.
Le liste Python sono mutabili, il che significa che assegnare una lista a una nuova variabile non crea una copia — entrambi i nomi puntano allo stesso object. Questa pagina spiega tutti i modi affidabili per copiare una lista, la differenza tra una copia superficiale e una copia profonda, e quando ciascun approccio è la scelta giusta.
La Trappola dell'Assegnazione
Un errore comune è usare l'operatore = aspettandosi che produca una copia indipendente:
Perché l'operatore = non copia una lista
Sia original che alias puntano allo stesso identico object lista in memoria. Qualsiasi modifica apportata tramite un nome è immediatamente visibile tramite l'altro.
Per ottenere una vera copia indipendente, utilizza uno dei metodi seguenti.
Metodi di Copia Superficiale
Una copia superficiale crea un nuovo object lista, ma gli elementi all'interno della nuova lista sono ancora riferimenti agli stessi object dell'originale. Per una lista piatta (una lista contenente solo valori immutabili come numeri e string), una copia superficiale si comporta come una copia indipendente completa.
Usare il Metodo copy()
Il metodo copy() è l'approccio più esplicito e leggibile:
Copiare una lista con il metodo copy()
original = ["apple", "banana", "cherry"]
copy_of = original.copy()
copy_of.append("date")
print(original) # Output: ['apple', 'banana', 'cherry']
print(copy_of) # Output: ['apple', 'banana', 'cherry', 'date']Le due liste sono ora indipendenti: aggiungere elementi a copy_of non influisce su original.
Usare la Notazione Slice [:]
La notazione slice è una scorciatoia Pythonica per copiare l'intera lista:
Copiare una lista con la notazione slice
original = [10, 20, 30, 40]
copy_of = original[:]
copy_of[0] = 99
print(original) # Output: [10, 20, 30, 40]
print(copy_of) # Output: [99, 20, 30, 40][:] si legge come "prendi ogni elemento dall'inizio alla fine," il che produce una nuova lista contenente quegli elementi.
Usare il Costruttore list()
Passare una lista esistente a list() crea anch'esso una copia superficiale:
Copiare una lista con il costruttore list()
original = [1, 2, 3]
copy_of = list(original)
copy_of.append(4)
print(original) # Output: [1, 2, 3]
print(copy_of) # Output: [1, 2, 3, 4]Questo è particolarmente utile quando si converte un altro iterabile (come una tupla) in una lista allo stesso tempo.
Quando le Copie Superficiali Non Bastano
Una copia superficiale copia solo la struttura di primo livello. Se la lista contiene object mutabili come altre liste o dizionari, quegli object annidati sono ancora condivisi tra l'originale e la copia.
Copia superficiale con una lista annidata
Entrambe le liste condividono gli stessi object lista interni [1, 2] e [3, 4]. Modificare original[0][0] cambia quella lista interna condivisa, quindi la modifica appare anche in shallow.
Copia Profonda
Una copia profonda copia ricorsivamente ogni object all'interno della lista, producendo una struttura completamente indipendente dall'originale. Usa copy.deepcopy() dal modulo standard copy:
Copia profonda di una lista annidata con copy.deepcopy()
import copy
original = [[1, 2], [3, 4]]
deep = copy.deepcopy(original)
original[0][0] = 99 # Mutate the nested list
print(original) # Output: [[99, 2], [3, 4]]
print(deep) # Output: [[1, 2], [3, 4]] <- unchangeddeep contiene le proprie copie delle liste interne, quindi le modifiche a original non lo influenzano affatto.
Copia Superficiale vs. Copia Profonda a Colpo d'Occhio
| Metodo | Crea nuova lista? | Copia object annidati? | Ideale per |
|---|---|---|---|
assegnazione = | No | No | Solo alias |
copy() | Sì | No (superficiale) | Liste piatte |
slicing [:] | Sì | No (superficiale) | Liste piatte |
list() | Sì | No (superficiale) | Liste piatte / iterabili |
copy.deepcopy() | Sì | Sì | Strutture annidate |
Esempi Pratici
Combinare Tutti i Metodi di Copia Superficiale
original = [1, 2, 3]
a = original.copy() # method
b = original[:] # slice
c = list(original) # constructor
original.append(4)
print(a) # Output: [1, 2, 3]
print(b) # Output: [1, 2, 3]
print(c) # Output: [1, 2, 3]Tutti e tre producono copie indipendenti — nessuna di esse riflette il successivo append(4).
Copiare una Lista di Dizionari
I dizionari sono object mutabili. Una copia superficiale di una lista di dizionari condivide quegli object dict:
import copy
records = [{"name": "Alice", "score": 90}, {"name": "Bob", "score": 85}]
shallow = records.copy()
deep = copy.deepcopy(records)
records[0]["score"] = 0
print(shallow[0]) # Output: {'name': 'Alice', 'score': 0} <- shared dict
print(deep[0]) # Output: {'name': 'Alice', 'score': 90} <- independent copyQuando gli elementi sono object mutabili e hai bisogno di piena indipendenza, usa sempre deepcopy().
Conclusione
Le liste Python sono mutabili, quindi l'operatore = crea un alias, non una copia. Per le liste piatte, qualsiasi metodo di copia superficiale — copy(), [:], o list() — funziona ugualmente bene. Quando le liste contengono object mutabili annidati, usa copy.deepcopy() per garantire la piena indipendenza.
Per esplorare operazioni correlate sulle liste, vedi Metodi delle Liste, Aggiungere Elementi a una Lista e Rimuovere Elementi da una Lista. Per la copia dei dizionari, vale la stessa distinzione superficiale/profonda — vedi Copiare i Dizionari.