Python: Perché la mia lista viene modificata globalmente?

👤 Iniziato da @jordanmorelli90
📅 12/06/2025 14:10
📁 Programmazione 🌐 IT
Avatar di jordanmorelli90
Ragazzi, ho un problema che mi sta facendo bestemmiare da un'ora. Ho creato una semplice funzione che dovrebbe lavorare su una copia di una lista, ma invece modifica l'originale! Ecco il codice maledetto:

```python
lista_originale = [1, 2, 3]

def modifica_lista(lista):
lista.append(999)
print("Dentro la funzione:", lista)

modifica_lista(lista_originale)
print("Fuori la funzione:", lista_originale) # Stampa [1,2,3,999]! PERCHÉ??
```
Secondo me è un comportamento del cazzo, ma probabilmente c'è una spiegazione logica che mi sfugge. Ho provato a copiare la lista con `list()` e pure con slicing `[:]`, ma a volte capita lo stesso. È colpa delle reference? Qualcuno mi spieghi sta follia delle variabili mutabili in Python perché sto per lanciare il PC dalla finestra. Come gestite voi queste situazioni? Consigli pratici, please, niente teoria da manuale.
Avatar di indigofarina
Ah, il classico tranello delle mutabilità! Capisco la tua frustrazione, mi è successo un sacco di volte all'inizio. È proprio come dici tu, è una questione di reference. In Python, quando passi una lista a una funzione, non ne passi una copia, ma un riferimento alla lista originale. Quindi qualsiasi modifica fai dentro la funzione, la fai sull'oggetto reale.

Quelle bestie di liste sono mutabili, a differenza di stringhe o tuple che sono immutabili. Se vuoi davvero lavorare su una copia indipendente, devi fare una copia profonda, soprattutto se hai liste annidate. La copia superficiale con `list()` o `[:]` funziona solo per il primo livello. Per una copia profonda ti serve `copy.deepcopy()`.

È una cosa che all'inizio fa impazzire, ma una volta che ci fai l'abitudine, capisci perché è così efficiente. Consigli pratici? Stai sempre attento con gli oggetti mutabili nelle funzioni, e se devi modificarli senza toccare l'originale, usa `deepcopy()`. Fidati, ti risparmierà un sacco di bestemmie future.
Avatar di sashagatti
Capisco la frustrazione, @jordanmorelli90, mi è successa la stessa cosa tante volte. Python e le sue mutabilità possono farti venire voglia di lanciare tutto per aria. @indigofarina ha centrato il punto: è tutta una questione di riferimenti. Quando passi una lista a una funzione, stai passando un riferimento all'oggetto originale, non una copia.

Ho un consiglio pratico che mi ha salvato la vita più volte: usa `copy.deepcopy()` per liste complesse, soprattutto se sono annidate. Per liste semplici, il slicing `[:]` di solito basta, ma non fidarti ciecamente. Ho imparato a mie spese che a volte non è sufficiente.

Un altro trucco è lavorare con tuple invece di liste quando possibile, dato che sono immutabili. Questo ti evita un sacco di grattacapi. E se proprio devi usare liste, fai tanti test con diversi casi per assicurarti che il comportamento sia quello che ti aspetti. Buona fortuna e non lanciare il PC, ti servirà per risolvere questi enigmi!
Avatar di amadeoricci83
Cazzo, ragazzi, capisco benissimo la frustrazione di @jordanmorelli90! Mi è capitato più di una volta di impazzire per colpa delle reference in Python. La spiegazione di @indigofarina è perfetta: quando passi una lista a una funzione, stai passando un riferimento, non una copia. E se la lista è annidata, `list()` o `[:]` non bastano, ci vuole `copy.deepcopy()` per una copia profonda.

Un consiglio che aggiungerei è di usare le tuple al posto delle liste quando non prevedi modifiche. Sono immutabili e ti salvano da questi casini. Io personalmente, quando devo lavorare con strutture complesse, uso sempre `deepcopy()` per stare tranquillo. E se proprio ti incasini, prenditi una pausa, magari vai a bere qualcosa con gli amici il weekend e ci ripensi con calma. Funziona sempre!
Avatar di soniagrassi85
Ah, che incubo, @jordanmorelli90! Capisco la rabbia, mi è successo durante un viaggio in treno mentre sistemavo codice sul cellulare... quasi ho lanciato il telefono dal finestrino! 🚆💥 La spiegazione degli altri è perfetta: in Python le liste sono come valigie condivise - se qualcuno ci mette dentro roba (anche per sbaglio), tutti vedono i cambiamenti.

Oltre a `deepcopy`, il mio lifehack è: crea NUOVE liste invece di modificare l'originale. Tipo:

```python
def modifica_lista_sicura(lista):
return [*lista, 999] # unpacking operator, magico!
```

Così preservi l'originale e hai una copia pulita. Per liste complesse, uso `lista.copy()` se è piatta, altrimenti deepcopy senza pietà. Un'altra dritta? Annota sempre nelle funzioni se modificano l'input (es. `# MUTA LA LISTA!`).

Quando mi incasino, faccio una pausa: mi prenoto un weekend low-cost su Skyscanner e torno col cervello resetatto. Prova, e tieni pronta una calamita per la next bug session! 😉🧳
Avatar di azegliograssi
Madonna santa Jordan, capisco il nervoso! Ti giuro che ho perso anni di vita per ste cavolo di reference in Python. Tutti han detto cose giuste, ma ecco la mia take da apprendista permanente dopo aver sbattuto la testa mille volte:

**La spiegazione rapida:**
Quando passi `lista_originale`, Python non fa una copia, ma ti dà le *chiavi della macchina*. Se la modifichi dentro alla funzione, la cambi ovunque. Slicing `[:]` e `list()` copiano solo il primo strato - se hai liste annidate, è merda.

**Consigli pratici che mi hanno salvato il fegato:**
1. **Per liste piatte:** usa `copia = lista_originale.copy()` o `copia = lista_originale[:]`
2. **Per liste annidate:** `import copy` e `copia = copy.deepcopy(lista_originale)` SEMPRE.
3. **Stile funzionale:** invece di modificare, CREA nuove liste:
```python
def modifica_lista(lista):
return lista + [999] # oppure [*lista, 999] come dice @soniagrassi85
```
4. **Debug pro:** stampa `id(lista)` dentro/fuori la funzione - se è uguale, è la stessa cazzo di lista!

Personalmente, quando vedo "Mutable Default Arguments" o ste robe, bestemmio in dialetto. Ma poi ricordo: Python è così, o lo domi o ti spolpa. Per liste complesse, ormai uso solo `deepcopy` e via, non mi fido più neanche di me stesso.

PS: Se lanci il PC, prendi un portatile di scorta. E magari un cuscino per urlarci dentro.
Avatar di sailortesta22
Ciao Jordan, tranqui, mi è successo pure a me di mandare in loop la testa per 'sta cosa. Le liste in Python sono come parenti invadenti: se gli dài accesso, ti modificano pure la spesa senza chiedere. Quando passi una lista a una funzione, non è una copia, è come dare le chiavi di casa a qualcuno... lui entra, aggiunge roba (tipo append) e tu dopo trovi il frigo pieno di 999 invece delle birre.

Per risolvere:
- Liste semplici? Usa `copia = lista_originale.copy()` o `copia = lista_originale[:]`, ma se annidi liste (es. [[1], [2]]), devi sbatterci sopra `deepcopy()` altrimenti il casino continua.
- Se vuoi stare tranquillo, ritorna una lista nuova: `return lista + [999]`. Così non spacchi nulla.
- Debugga con `id(lista)` dentro e fuori la funzione — se coincidono, stai giocando con lo stesso oggetto.

Io ho imparato a odiare le mutazioni in-place. Ora uso tuple dove posso o clono col deepcopy. E quando il codice mi prende per il culo, mi alzo e vado a correre. Il cervello si resetta, giuro. 🏃♂️💨
Avatar di jordanmorelli90
Sailortesta22, grazie! La metafora del parente invadente col frigo mi ha fatto sputare il caffè 🤣 Hai messo il dito nella piaga: usavo `append()` come un elefante in cristalleria. Ho provato con `copy()` ma dentro c'era una lista di liste... quindi domani mi compro una maglietta "I ❤️ deepcopy".
Quel trick di `id(lista)` è oro, già debugato e confermo: stesso oggetto, stesso disastro. Da oggi vivo di tuple e ritorno liste nuove, giuro. E se il codice si ribella, seguo il tuo consiglio: corsa selvaggia → reset neurale ✅ Grazie per avermi salvato dal manicomio!

La Tua Risposta

💬

Vuoi partecipare alla discussione?

Accedi o registrati per scrivere la tua risposta e unirti alla conversazione!