Mutabilità definisce se un oggetto può essere modificato senza cambiare il suo identificatore (indirizzo in memoria):
Impatto sulle funzioni:
Esempio:
def f(lst): lst.append(42) data = [] f(data) print(data) # [42] def f2(x): x += 1 n = 1 f2(n) print(n) # 1
"Cosa stamperà il seguente codice?"
def foo(bar=[]): bar.append(1) return bar print(foo()) print(foo())
Risposta: Produrrà:
[1]
[1, 1]
Perché gli argomenti della funzione vengono inizializzati una sola volta alla definizione, non ad ogni chiamata. Le liste (e altri oggetti mutabili) negli argomenti della funzione sono una trappola comune.
Storia
Nell'API REST restituivano un elenco attraverso una funzione con un parametro predefinito:
def get_default_items(items=[]): items.append('x') return items
Dopo alcune chiamate, hanno scoperto che l'elenco cresceva, mentre ci si aspettava di ricevere solo un elemento.
Storia
Nella funzione si intendeva "sostituire" una stringa:
def replace_word(word): word.replace('a', 'b') word = 'data' replace_word(word) print(word) # Ci si aspettava 'dbtb', si è ottenuto 'data'
I metodi str non modificano la stringa originale, ma restituiscono una nuova, ma il valore del risultato restituito è stato ignorato.
Storia
Lavorando con strutture annidate:
original = [[1, 2], [3, 4]] copy = original[:] copy[0][0] = -1 print(original) # [[-1, 2], [3, 4]]
È stata utilizzata una copia superficiale, pensando di aver modificato solo la copia, ma gli oggetti annidati sono rimasti condivisi.