Oltre alle liste, esistono in Python altri tipi di dato derivati che hanno caratteristiche simili.
La tuple è anch'essa un insieme di oggetti. L'unica differenza
con la lista è che essa non può più essere modificata una volta inizializzata, cioè i suoi elementi non possono
più essere cambiati. Possiamo quindi leggerli, ma non scriverli, nè usare funzioni che la modificano, come
append(), sort()
. Si dice che la list
è un oggetto
mutable, mentre la tuple
è immutable.
Per creare una tuple
si scrivono i suoi elementi tra parentesi tonde. Proviamo con IDLE (ho
commentato il codice per una migliore comprensione):
>>> citta = ("Roma", "Milano", "Napoli") # una tuple di 3 stringhe >>> len(citta) # ok, non sto cambiando la tuple
3
>>> citta[1] # ok, sto leggendo un valore
'Milano'
>>> citta[2] = "Torino" # errore, sto cercando di cambiare un valore
Traceback (most recent call last): File "<pyshell#10>", line 1, in <module> citta[2] = "Torino" TypeError: 'tuple' object does not support item assignment
Probabilmente vi starete chiedendo: che bisogno c'è di un tipo di dato uguale alla lista, ma che fa meno cose? Il motivo è l'efficienza: ho già detto che la filosofia di Python è quella di nascondere il più possibile il lavoro che lui fa nella memoria del computer, in modo che il programmatore non se ne deva preoccupare. Tuttavia bisogna rendersi conto che maneggiare una lista è un'operazione molto gravosa dal punto di vista della gestione della memoria (dato che la lista può allungarsi e accorciarsi, Python non sa a priori quanto spazio essa occuperà, e quindi è costretto a cancellarla e riscriverla continuamente nella memoria del computer).
Usare una tuple
è per Python molto più semplice: poichè non può più essere modificata richiede
una quantità fissa di memoria e quindi meno tempo di elaborazione rispetto ad una lista. I programmatori esperti
usano tipicamente le tuple
quando è necessario creare delle tabelle di valori predefiniti che non
varieranno più per tutto il programma e dalle quali ci sarà bisogno solo di leggere i dati.
>>> classe_prima_B = ("Abate", "Bartoli", "Concia") #ecc.
>>> citta_lazio = ("Viterbo", "Latina", "Rieti", "Frosinone", "Roma")
Infine va detto che Python accetta una tuple
anche senza scrivere le parentesi, semplicemente
scrivendo i suoi elementi separati da virgole:
>>> numeri = 1, 2, 3, 4, 5 >>> type(numeri)
<class 'tuple'>
Questa doppia possibilità può disorientare i principianti, ma la segnalo ugualmente perchè si può trovare leggendo un programma scritto da altri. In particolare questa sintassi permette l'assegnazione multipla, usata molto spesso nel linguaggio perchè permette di "risparmiare" linee di codice:
a, b, c = 1, 2, 3
possiamo cioè assegnare in una sola istruzione più variabili: vengono prima calcolate tutte le espressioni a destra, poi vengono create due tuple temporanee e la tuple a destra è assegnata a quella a sinistra. A sinistra ci deve essere lo stesso numero di variabili delle espressioni a destra.
In ogni caso, data la facilità con cui ci si può confondere e generare errori inaspettati,
consiglio per il momento di usare sempre le liste, lasciando la distinzione tra list
e
tuple
a quando sarete più esperti.
Il range è ancora più semplice: è solo una sequenza di numeri interi, anch'essa
unmutable. Può essere creato con la funzione range()
, che ha
tre sintassi possibili:
Funzione | Significato |
---|---|
range(stop) |
I numeri da 0 a stop - 1 (stop non è mai compreso) |
range(start, stop) |
I numeri da start (compreso) a stop (non compreso) |
range(start, stop, step) |
I numeri a step a step partendo da start . step
può essere anche negativo per ottenere un range di numeri decrescenti. L'ultimo
numero è minore di start se step è positivo, maggiore se
step è negarivo |
Vediamo qualche esempio in IDLE:
>>> range(10) # i numeri da 0 a 9
>>> range(-2) # vuoto: stop e' < 0
>>> range(3, 12) # i numeri da 3 a 11
>>> range(-6, 0) # i numeri da -6 a -1
>>> range(-2, 13, 3) # i numeri (-2, 1, 4, 7, 11) (fino all'ultimo numero < 13)
>>> range(10, 0, -1) # i numeri decrescenti da 10 a 1 (0 non e' compreso)
Notate che nel caso del range
IDLE vi risponde soltanto ripetendo range(10)
,
ecc. senza farvi vedere gli elementi uno per uno. Anche la print()
ha lo stesso comportamento.
In ogni modo, le list
, le tuple
ed i range
si possono convertire
uno nell'altro mediante apposite funzioni di conversione (ma non si può convertire una list
o tuple
in un range
).
Ad esempio, immaginiamo di avere bisogno di una lista con i primi 10000 numeri interi: scriverli uno
per uno sarebbe decisamente seccante! Possiamo però facilmente ottenerli come range
e poi
trasformarlo in list
a = range(10000)
b = list(a) # una list con 10000 elementi, impossibile da scrivere a mano
b = list(range(10000)) # meglio ancora: una sola istruzione
Provate adesso a chiedere ad IDLE il valore di b
...
range()
questi insiemi di numeri (per visualizzarli
e controllare dovete convertirli in liste):
[ 1, 2, 3, 4, ... 100 ]
[ 2, 4, 6, 8, ... 200 ]
[ 1, 5, 9, 13, ... 1001 ]
[ 10, 8, 6, 4, 2, 0 ]
[ -1, -2, -3, -4, ... -10 ]
SOLUZIONITrue
o False
>>> 0 in range(20)
>>> 10 in range(20)
>>> 20 in range(20)
>>> 1 in range(1, 20)
>>> 2 in range(1, 20, 2)
>>> 19 in range(1, 20, 2)
>>> 5 in range(10, 1, -1)
>>> 2 in range(10, 1, -1)
Vedremo nella prossima lezione la notevole utilità dei range
, soprattutto quando sono abbinati
all'istruzione for
.
Il meccanismo degli indici funziona anche per le stringhe, per le quali possiamo indicare i singoli caratteri mediante la loro posizione nella stringa. Python restituirà una stringa formata dal solo carattere corrispondente. Ecco un esempio in IDLE;
>>> s = "Mamma mia!" >>> s[0]
'M'
>>> s[4]
'a'
>>> s[5]
' '
>>> s[1] + s[9]
'a!'
Le stringhe sono comunque un tipo di dato immutable, quindi non è possibile usare gli indici per
modificarle, nè, ovviamente, usare su di esse le funzioni proprie delle liste. Ricordiamo però che, al posto della
append()
, possiamo sempre usare la concatenazione (somma tra stringhe). continuate così:
>>> s[2] = "t"
Traceback (most recent call last): File "
", line 1, in s[2] = "t" TypeError: 'str' object does not support item assignment >>> s.append(10 *s[9])
Traceback (most recent call last): File "
", line 1, in s.append(10 * s[9]) AttributeError: 'str' object has no attribute 'append' >>> s += (10 * s[9]) >>> s
'Mamma mia!!!!!!!!!!!'
Fine della lezione