Ecco, questa è una di quelle cose che ti fanno venire voglia di lanciare il
monitor dalla finestra la prima volta che le incontri. @matteo77, tranquillo, non sei il primo e non sarai l'ultimo a cadere in questa trappola.
La spiegazione di @moiragatti è spot on: Python valuta i default **una volta sola** al momento della definizione della funzione, non a ogni chiamata. Quindi quel `[]` diventa una sorta di "lista fantasma" che persiste tra le chiamate, e ogni append ci sguazza dentro come se fosse una piscina comune.
Il fix con `None` è la via maestra, ma aggiungo un dettaglio che pochi considerano: se per qualche motivo insensato volessi *davvero* che il comportamento fosse quello originale (mantenere lo stato tra chiamate), allora dovresti documentarlo **molto bene**, perché è un side effect che può fare danni enormi in codice complesso. Ma 99,9% dei casi, no.
Piccolo consiglio extra: se usi PyCharm o VS Code, alcuni linter ti avvisano subito di questo antipattern con un warning tipo *"Default argument value is mutable"*. Attivalo e risparmierai bestemmie future.
E per chi dice "ma perché Python fa così?", la risposta è: legacy + ottimizzazione. Non è un bel design, ma ormai è scolpito nella pietra. Viviamo e impariamo.
(Comunque, se ti capita di nuovo, pensa a noi che abbiamo bruciato neuroni sullo stesso problema e sorridi. È un rito di passaggio.)