Mutable e Immutable in Python

Mutable e Immutable in Python

Questo articolo spiega il concetto di mutable e immutable in Python.

YouTube Video

Mutable e Immutable in Python

"Mutable" e "immutable" si riferiscono alla mutabilità di un oggetto. Comprenderlo aiuta a evitare bug inattesi e a gestire la memoria in modo efficiente.

Cosa significa Mutable?

Gli oggetti mutable possono cambiare il loro stato interno dopo la creazione.

Principali tipi di dato Mutable

  • list
  • dict
  • set
  • Classi definite dall'utente (se i loro attributi possono essere modificati)

Esempio: Modifica di una lista

1numbers = [1, 2, 3]
2numbers[0] = 100
3print(numbers)  # [100, 2, 3]

Una lista è un oggetto mutable e i suoi elementi possono essere modificati liberamente.

Cosa significa Immutable?

Gli oggetti immutable non possono essere modificati una volta creati. Tentare di modificarli comporta la creazione di un nuovo oggetto.

Principali tipi di dato Immutable

  • int
  • float
  • str
  • tuple
  • bool
  • frozenset

Esempio: Modifica di una stringa

1text = "hello"
2# text[0] = "H"  # TypeError: 'str' object does not support item assignment
3
4text = "H" + text[1:]  # Creates a new string
5print(text)  # "Hello"

Le stringhe sono immutable, quindi non possono essere modificate parzialmente.

Confronto tra Mutable e Immutable

 1# Mutable example
 2a = [1, 2, 3]
 3b = a
 4b[0] = 100
 5print(a)  # [100, 2, 3] -> a is also changed
 6
 7# Immutable example
 8x = 10
 9y = x
10y = 20
11print(x)  # 10 -> x is unchanged

Come si può vedere da questo esempio, gli oggetti mutabili vengono condivisi per riferimento, quindi possono influenzare altre variabili. D'altra parte, gli oggetti immutabili creano nuove istanze durante la riassegnazione, lasciando il valore originale invariato.

Esaminare il Comportamento Interno Usando id()

In Python, puoi usare la funzione id() per controllare l'ID di un oggetto. L'ID di un oggetto è simile a un indirizzo di memoria.

 1# Immutable int behavior
 2a = 10
 3print(id(a))  # e.g., 140715920176592
 4a += 1
 5print(id(a))  # e.g., 140715920176624 -> ID has changed
 6
 7# Mutable list behavior
 8b = [1, 2, 3]
 9print(id(b))  # e.g., 2819127951552
10b.append(4)
11print(id(b))  # Same ID -> only the content has changed

Come mostrato, un nuovo oggetto viene creato per i tipi immutabili, mentre i tipi mutabili vengono modificati in loco.

Funzioni e Attenzione con Oggetti Mutabili e Immutabili

Quando si passa un oggetto mutabile a una funzione, i dati originali possono essere modificati.

Esempio: Una Funzione che Modifica una Lista

1def modify_list(lst):
2    lst.append(100)
3
4my_list = [1, 2, 3]
5modify_list(my_list)
6print(my_list)  # [1, 2, 3, 100]

Esempio: Una Funzione che Modifica un Numero

D'altra parte, tentare di modificare un oggetto immutabile comporta la creazione di un nuovo oggetto.

1def modify_number(n):
2    n += 10
3
4my_number = 5
5modify_number(my_number)
6print(my_number)  # 5 -> unchanged

Considerazioni Pratiche

Evita di Usare Oggetti Mutabili come Argomenti di Default

 1# Bad example
 2def add_item(item, container=[]):
 3    container.append(item)
 4    return container
 5
 6print(add_item(1))  # [1]
 7print(add_item(2))  # [1, 2] -> unintended behavior
 8
 9# Good example
10def add_item(item, container=None):
11    if container is None:
12        container = []
13    container.append(item)
14    return container
15
16print(add_item(1))  # [1]
17print(add_item(2))  # [2]

Poiché gli argomenti di default vengono valutati solo una volta alla definizione della funzione, l'uso di oggetti mutabili può portare a effetti collaterali inattesi.

  • Nel primo esempio, lo stesso oggetto lista viene utilizzato ogni volta che si chiama add_item. Quando si chiama add_item(2) la seconda volta, l'elemento 1 aggiunto in precedenza è ancora presente nella lista, risultando in [1, 2].
  • Nell'esempio migliorato, None viene usato come valore predefinito e una nuova lista viene creata all'interno della funzione se l'argomento è None. Questo garantisce che una nuova lista venga creata ogni volta che la funzione viene chiamata, così i risultati precedenti non influenzano le chiamate successive.

Evita di usare oggetti mutabili come liste o dizionari come argomenti predefiniti; usa invece None e inizializzali all'interno della funzione. Questa è una buona pratica fondamentale e importante in Python.

Riepilogo

Per comprendere a fondo le variabili e i tipi di dati di Python, è fondamentale afferrare le differenze tra mutabile e immutabile. Comprendere queste caratteristiche ti aiuta ad evitare comportamenti indesiderati nel tuo codice e a scrivere programmi più robusti e leggibili.

Puoi seguire l'articolo sopra utilizzando Visual Studio Code sul nostro canale YouTube. Controlla anche il nostro canale YouTube.

YouTube Video