Martedì 27 ottobre 2026
L’edizione di oggi
Millebit
AI · Software · QA
Il segnale, non il rumore.

Gli articoli di Millebit sono scritti con l’intelligenza artificiale a partire da fonti citate in ogni pezzo. Come lavoriamo

QA e affidabilità

Refactor di liste in Python rompe il chiamante senza errori

Testo scritto con l’intelligenza artificiale a partire da una fonte citata, senza revisione umana prima della pubblicazione.

Sostituire una mutazione in-place con la restituzione di una nuova lista può lasciare il codice che ha passato l'oggetto a leggere una versione obsoleta, con bug silenziosi.

Illustrazione generata con l’intelligenza artificiale

Cambiare rows.sort() in rows = sorted(rows) e vedere i test verdi può mandare in produzione un bug silenzioso: il chiamante continua a leggere la lista vecchia1.

Il post spiega che la mutazione in-place è spesso parte silenziosa del contratto di un modulo. Molti test verificano il valore di ritorno di una funzione. Quasi nessuno controlla se la lista del chiamante è cambiata sotto i suoi piedi. Così, sostituire una mutazione con una copia lascia verde la suite. In produzione, però, il codice legge ancora l’oggetto originario, nell’ordine originario1.

Il punto è l’aliasing, non la logica. Un chiamante passa una lista. La funzione la modifica e restituisce None. Il chiamante non legge il return, legge la sua variabile più tardi. Questo è un contratto reale che vive fuori dalle asserzioni. Arriva il refactor: ora la funzione restituisce una lista nuova. I test sul valore di ritorno passano. Il chiamante conserva il suo oggetto stantio. Nessuna eccezione. Nessun log di errore. Il danno è silenzioso perché la firma non è cambiata. Quindi il varco deve registrare le mutazioni, non solo gli output1.

L’esempio più chiaro è l’ordinamento. rows.sort() muta la lista ricevuta. rows = sorted(rows) restituisce una lista ordinata nuova. Se il chiamante si aspetta che la propria lista sia stata riordinata in loco, il refactor spezza quell’aspettativa. Un test che guarda solo il return non se ne accorge, la produzione sì1.

Per proteggere questa cucitura tra copia e mutazione, l’autore invita a “congelarla” prima di toccare il corpo della funzione. Serve rendere visibili le mutazioni come parte del contratto, non basta verificare l’output1.

La proposta concreta è un “mutation ledger”. Una piccola sonda avvolge la funzione. Scatta uno snapshot profondo di ogni argomento prima della chiamata. Dopo l’esecuzione, calcola una differenza per ciascun argomento e aggiunge una riga JSON per ogni invocazione. In questo modo, chiamata per chiamata, resta traccia di ciò che è cambiato sugli argomenti passati1.

Il post include un modulo di esempio, mutation_probe.py. Importa copy, functools e json. La funzione interna _snapshot prova a eseguire una deepcopy dell’argomento, così da congelare lo stato pre-chiamata. Dopo la chiamata, il probe confronta gli argomenti e appende il risultato come singola riga JSON per ogni invocazione1.

Questa traccia di mutazioni espone il confine tra alias condivisi e oggetti nuovi. Il ledger registra se un argomento è cambiato durante la chiamata. Se un refactor sostituisce una mutazione con una copia, la differenza tra prima e dopo lo rende evidente anche quando i test di ritorno restano verdi1.

L’implicazione pratica è chiara: quando una funzione può mutare i propri argomenti, il contratto non vive solo nel valore di ritorno. Va congelato e reso osservabile. Prima del refactor, costruire un registro delle mutazioni riduce il rischio di rompersi in silenzio pur con la suite che passa1.

Fonti

  1. Your Refactor Copies a List. The Caller Still Holds the Old One. dev.to · 27 ottobre 2026
Come è nato questo articolo Scritto da un sistema di intelligenza artificiale, con controlli automatici

Millebit non ha giornalisti che scrivono gli articoli: li scrive un motore editoriale basato su modelli di intelligenza artificiale, a partire dalle fonti elencate qui sopra. Prima di uscire, ogni testo passa questi controlli:

  • Fedeltà alle fonti. Un secondo passaggio toglie ogni affermazione che le fonti non sostengono. Valutazione su questo pezzo: 9,5/10.
  • Anti-cliché. Un filtro scarta frasi fatte, enfasi e tic della prosa artificiale: superato.
  • Giudizio editoriale. Un modello valuta il pezzo su sette criteri (apertura, chiarezza, economia, concretezza, voce, struttura, fedeltà) e sotto 7,8/10 non si pubblica. Questo articolo ha preso 8,2/10.

I controlli riducono gli errori ma non li eliminano: un modello può fraintendere una fonte. Per le decisioni importanti, risali alla fonte originale. Se trovi un errore, segnalacelo.

Come funziona Millebit, nel dettaglio →

Hai trovato un errore? Segnalacelo
Tipo di segnalazione

Leggiamo ogni segnalazione. Le correzioni fatte sono elencate in Correzioni. L’email, se la lasci, serve solo a risponderti.