Corso Python / Tuple e unpacking: separare valori e capire l’immutabilità

Una tupla Python è una sequenza ordinata i cui elementi non possono essere sostituiti. È utile per piccoli record e per separare più valori con l’unpacking, ma un oggetto modificabile contenuto nella tupla può ancora cambiare.

Creare una tupla e capire che cosa resta immutabile

È la virgola a creare una tupla non vuota; le parentesi rendono il raggruppamento più chiaro. Una tupla con un solo elemento richiede la virgola finale: (3500,). L’espressione (3500) è invece semplicemente l’intero 3500 tra parentesi. La tupla vuota si scrive ().

single = (3500,)
record = ("lunch", 8000)
print(type(single).__name__)
print(record[0])

Il programma stampa tuple e poi lunch su due righe: il primo risultato verifica il tipo, il secondo legge la posizione 0 del record. Come nelle liste e nelle stringhe, gli indici iniziano da zero; la tupla mantiene l’ordine degli elementi.

Non puoi assegnare un nuovo valore a record[0]. Puoi però associare il nome record a un’altra tupla: l’immutabilità riguarda l’oggetto, non impedisce una nuova assegnazione al nome. La guida ufficiale alle tuple e alle sequenze mostra queste forme e l’unpacking.

Eseguire un esempio completo di unpacking

L’unpacking assegna gli elementi di una sequenza a più nomi. Salva il seguente programma in UTF-8 come tuples.py, dentro una cartella di esercitazione, ed esegui python tuples.py con l’interprete del progetto selezionato. Su macOS o Ubuntu fuori dall’ambiente virtuale usa python3 se è il comando dell’interprete scelto. Non sono necessari pacchetti esterni.

record = ("lunch", 8000, "food")
name, amount, category = record
print(name, amount, category)
first, *rest = [3500, 8000, 2500]
print(first, rest)
a, b = 1, 2
a, b = b, a
print(a, b)

Il risultato atteso è:

lunch 8000 food
3500 [8000, 2500]
2 1

I tre nomi della prima assegnazione ricevono, nell’ordine, nome della spesa, importo e categoria. first riceve poi 3500, mentre rest raccoglie gli altri importi in una lista, come mostrano le parentesi quadre nell’output. Nell’ultima parte il lato destro b, a viene valutato prima delle assegnazioni: i valori 1 e 2 vengono così scambiati senza una variabile temporanea esplicita.

Controllare quantità, significato e oggetti interni

Senza un destinatario con asterisco, il numero di elementi deve corrispondere al numero di nomi: tre elementi per name, amount, category. Se ne arrivano due o quattro, Python genera ValueError. Se invece i tre elementi sono presenti ma in ordine sbagliato, l’assegnazione può riuscire pur attribuendo significati errati: l’unpacking controlla la struttura, non il significato dei campi.

Un nome con asterisco, come *rest, riceve una lista con gli elementi rimanenti, anche quando non ne rimane nessuno. In uno stesso elenco di destinatari, allo stesso livello, può esserci un solo destinatario con asterisco. La specifica delle assegnazioni descrive le regole anche per strutture annidate.

Attraversare direttamente un dizionario restituisce le chiavi. Per ottenere coppie chiave-valore usa items() e separa i due elementi di ciascuna coppia. Per dati ricevuti da file o rete verifica prima il numero e il significato dei campi, senza assumere che tutti i record abbiano la stessa forma.

Con pair = ([1], 2), l’istruzione pair[0] = [] genera TypeError: prova a sostituire un elemento della tupla. Invece pair[0].append(3) modifica la lista già presente e produce ([1, 3], 2). La distinzione tra riferimento e contenuto è la stessa che aiuta a capire le copie superficiali delle liste.

Scegliere tuple, liste o campi con un nome

Esigenza Struttura da considerare
Importi a cui aggiungere nuovi elementi Lista modificabile.
Piccolo insieme di campi con posizioni note Tupla, con l’ordine documentato.
Molti campi da identificare con nomi significativi Dizionario oppure dataclass, secondo il modello dei dati.

Per usare una tupla come chiave di un dizionario, tutti i suoi elementi devono essere hashable, cioè compatibili con il meccanismo di hash delle chiavi. Una tupla di stringhe e interi può esserlo; una tupla che contiene una lista non lo è e genera TypeError se usata come chiave. Un contenitore esterno immutabile non rende automaticamente hashable tutto ciò che contiene.

  1. Togli "food" dal record iniziale lasciando tre nomi nell’assegnazione: verifica il ValueError.
  2. Adatta anche l’assegnazione a name, amount e la stampa a print(name, amount): il record a due campi torna a funzionare.
  3. Ripristina il record a tre campi, i tre nomi e la stampa originale. Riesegui il file e confronta tutte le righe con il risultato atteso.

Quando devi ricordare continuamente se la seconda o la terza posizione rappresenta l’importo, valuta campi con un nome esplicito. La scelta deve rendere chiaro il significato dei dati, oltre a consentirne l’accesso.