Oggi introdurremo un nuovo costrutto di Python, la tupla. Fate molta attenzione, i costrutti che d’ora in avanti presenterò, (insieme alle liste presentate nella lezione precedente) sono usati praticamente sempre in Python. Quindi è bene acquisire una certa familiarità con essi. Fate molto esercizio!
La Mutabilità e le tuple
Finora avete visto due tipi composti: le stringhe (sequenze di caratteri) e le liste (sequenze di elementi di tipo qualsiasi). Una delle differenze che abbiamo notato è che le gli elementi di una lista possono essere modificati, mentre non possono essere alterati i caratteri in una stringa: le stringhe sono infatti immutabili mentre le liste sono mutabili.
C’`e un altro tipo di dati in Python, simile alla lista eccetto per il fatto che è immutabile: la tupla. La tupla è una lista di valori separati da virgole:
>>> tupla = ’a’, ’b’, ’c’, ’d’, ’e’
Sebbene non sia necessario, è convenzione racchiudere le tuple tra parentesi tonde per ragioni di chiarezza:
>>> tupla = (’a’, ’b’, ’c’, ’d’, ’e’)
Per creare una tupla con un singolo elemento dobbiamo aggiungere la virgola finale dopo l’elemento:
>>> t1 = (’a’,) >>> type(t1) <type ’tuple’>
Senza la virgola, infatti, Python tratterebbe (’a’) come una stringa tra parentesi:
>>> t2 = (’a’) >>> type(t2) <type ’string’>
Sintassi a parte le operazioni sulle tuple sono identiche a quelle sulle liste. L’operatore indice seleziona un elemento dalla tupla:
>>> tupla = (’a’, ’b’, ’c’, ’d’, ’e’) >>> tupla[0] ’a’
e l’operatore porzione seleziona una serie di elementi consecutivi:
>>> tupla[1:3] (’b’, ’c’)
A differenza delle liste se cerchiamo di modificare gli elementi di una tupla otteniamo un messaggio d’errore:
>>> tupla[0] = ’A’ TypeError: object doesn’t support item assignment
Naturalmente anche se non possiamo modificare gli elementi di una tupla possiamo sempre rimpiazzarla con una sua copia modificata:
>>> tupla = (’A’,) + tupla[1:] >>> tupla (’A’, ’b’, ’c’, ’d’, ’e’)
Assegnazione di tuple
Di tanto in tanto può essere necessario scambiare i valori di due variabili. Con le istruzioni di assegnazione convenzionali dobbiamo usare una variabile temporanea. Per esempio per scambiare a e b:
>>> temp = a >>> a = b >>> b = temp
Questo approccio è poco intuitivo e l’uso dell’assegnazione di tuple lo rende decisamente più comprensibile:
>>> a, b = b, a
La parte sinistra dell’assegnazione è una tupla di variabili; la parte destra una tupla di valori. Ogni valore è assegnato alla rispettiva variabile. Tutte le espressioni sulla destra sono valutate prima delle assegnazioni. Questa caratteristica rende le tuple estremamente versatili.
Ovviamente il numero di variabili sulla sinistra deve corrispondere al numero di valori sulla destra:
>>> a, b, c, d = 1, 2, 3 ValueError: unpack tuple of wrong size
Tuple come valori di ritorno
Le funzioni possono ritornare tuple. Per fare un esempio possiamo scrivere una funzione che scambia due valori:
def Scambia(x, y): return y, x
e in seguito possiamo assegnare il valore di ritorno della funzione ad una tupla di due variabili:
a, b = Scambia(a, b)
In questo caso non c’è una grande utilità nel rendere Scambia una funzione. Anzi
occorre stare attenti ad uno dei pericoli insiti nell’incapsulamento di Scambia: def Scambia(x, y): # versione non corretta
x, y = y, x
Se chiamiamo la funzione con:
Scambia(a, b)
apparentemente tutto sembra corretto, ma quando controlliamo i valori di a e b prima e dopo lo “scambio” in realtà ci accorgiamo che questi non sono cambiati. Perché? Perché quando chiamiamo questa funzione non vengono passate le variabili a e b come argomenti, ma i loro valori. Questi valori vengono assegnati a x e y; al termine della funzione, quando x e y vengono rimosse perché variabili locali, qualsiasi valore in esse contenuto viene irrimediabilmente perso.
Questa funzione non produce messaggi d’errore ma ciononostante non fa ciò che noi volevamo farle fare: questo è un esempio di errore di semantica.
Anche per le tuple è tutto. Alla prossima lezione ragazzi!