Lezione 8 Python Le Liste

      Nessun commento su Lezione 8 Python Le Liste

ATTENZIONE: Le liste trattate ora sono intese come array. In Python i normali array che si usano negli altri linguaggi sono chiamati liste. Dunque attenzione e non confondete le liste che tratteremo in questa lezione con le liste intese come strutture dinamiche che studieremo fra qualche lezione!

Liste

Una lista è una serie ordinata di valori, ognuno identificato da un indice. I valori che fanno parte della lista sono chiamati elementi. Le liste sono simili alle stringhe essendo insiemi ordinati di caratteri, fatta eccezione per il fatto che gli elementi di una lista possono essere di tipo qualsiasi. Liste e stringhe (e altri tipi di dati che si comportano da insiemi ordinati) sono chiamate sequenze.

Valori della lista

Ci sono parecchi modi di creare una lista nuova, e quello più semplice è racchiudere i suoi elementi tra parentesi quadrate ([ e ]):

[10, 20, 30, 40]
["Pippo", "Pluto", "Paperino"]

Il primo esempio è una lista di quattro interi, il secondo una lista di tre stringhe. Gli elementi di una stessa lista non devono necessariamente essere tutti dello stesso tipo. Questa lista contiene una stringa, un numero in virgola mobile, un intero ed un’altra lista:

["ciao", 2.0, 5, [10, 20]]

Una lista all’interno di un’altra lista è detta lista annidata. Le liste che contengono numeri interi consecutivi sono così comuni che Python fornisce un modo semplice per crearle:

>>> range(1,5)
[1, 2, 3, 4]

La funzione range prende due argomenti e ritorna una lista che contiene tutti gli interi a partire dal primo (incluso) fino al secondo (escluso).

Ci sono altre due forme per range. Con un solo argomento crea una lista a partire da 0:

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Se è presente un terzo argomento questo specifica l’intervallo tra valori succes- sivi, chiamato passo. Questo esempio mostra come ottenere una stringa dei numeri dispari tra 1 e 10:

>>> range(1, 10, 2)
[1, 3, 5, 7, 9]

Infine esiste una lista speciale che non contiene alcun elemento: è chiamata lista vuota ed è indicata da [].

Con tutti questi modi di creare liste sarebbe un peccato non poter variare il contenuto di una lista o poter passare liste come parametri di funzioni. Infatti entrambe queste cose possono essere fatte:

[code lang=”objc”]
>>> Vocabolario = ["amico", "casa", "telefono"]
>>> Numeri = [17, 123]
>>> ListaVuota = []
>>> print Vocabolario, Numeri, ListaVuota
[’amico’, ’casa’, ’telefono’] [17, 123] []
[/code]

Accesso agli elementi di una lista

La sintassi per l’accesso agli elementi di una lista è la stessa che abbiamo già visto per i caratteri di una stringa: anche in questo caso facciamo uso dell’operatore porzione ([]). L’espressione tra parentesi quadrate specifica l’indice dell’elemento (non dimenticare che gli indici partono da 0!):

[code lang=”objc”]
<pre>>>> print Numeri[0]
17
>>> Numeri[1] = 5
[/code]

L’operatore porzione può comparire in qualsiasi posto di un’espressione: quando è alla sinistra di un’assegnazione cambia uno degli elementi della lista (nell’esempio appena visto l’elemento 123 è diventato 5).

Come indice possiamo inoltre usare qualsiasi espressione che produca un intero:

>>> Numeri[3-2]
5
>>> Numeri[1.0]
TypeError: sequence index must be integer

Provando a leggere o modificare un elemento che non esiste si ottiene un messaggio d’errore:

>>> Numeri[2] = 5
IndexError: list assignment index out of range

Se un indice ha valore negativo il conteggio parte dalla fine della lista:

>>> Numeri[-1]
5
>>> Numeri[-2]
17

>>> Numeri[-3]
IndexError: list index out of range

Numeri[-1] è quindi l’ultimo elemento della lista, Numeri[-2] il penultimo e Numeri[-3] non esiste essendo la nostra lista composta di 2 soli elementi.

E` comune usare una variabile di ciclo come indice di una lista:

[code lang=”objc”]
<pre>Squadre = ["Juventus", "Inter", "Milan", "Roma"]</pre>
i=0
while i < 4:

print Squadre[i] i=i+1

[/code]

Questo ciclo while conta da 0 a 4: quando l’indice del ciclo i vale 4 la condizione diventa falsa e il ciclo termina. Il corpo del ciclo è eseguito solo quando i è 0, 1, 2 e 3.

Ad ogni ciclo la variabile i è usata come indice della lista: questo tipo di elaborazione è chiamata elaborazione trasversale di una lista o attraversamento di una lista.

Lunghezza di una lista

La funzione len ritorna la lunghezza di una lista. E` sempre bene usare len per conoscere il limite superiore in un ciclo, piuttosto che usare un valore costante: in questo modo se la lunghezza della lista dovesse cambiare non dovrai scorrere il programma per modificarne i cicli, e sicuramente len funzionerà correttamente per liste di ogni lunghezza:

[code lang=”objc”]
Squadre = ["Juventus", "Inter", "Milan", "Roma"]</pre>
i=0
while i < len(Squadre):

print Squadre[i] i=i+1

[/code]

L’ultima volta che il ciclo è eseguito i vale len(Squadre) – 1 che è l’indice dell’ultimo elemento della lista. Quando al successivo incremento i diventa len(Squadre) la condizione diventa falsa ed il corpo non è eseguito, dato che len(Squadre) non è un indice valido.

Sebbene una lista possa contenere a sua volta un’altra lista questa lista annidata conta come un singolo elemento indipendentemente dalla sua lunghezza. La lunghezza della lista seguente è 4:

[’ciao!’, 1, [’mela’, ’pera’, ’banana’], [1, 2, 3]]

Appartenenza ad una lista

“in” è un operatore booleano (restituisce vero o falso) che controlla se un valore è presente in una lista. L’abbiamo già usato con le stringhe ma funziona anche con le liste e con altri tipi di sequenze:

[code lang=”objc”]
<pre>>>> Squadre = [’Juventus’, ’Inter’, ’Milan’, ’Roma’]
>>> ’Inter’ in Squadre
1
>>> ’Arsiero’ in Squadre
[/code]

0
Dato che Inter è un membro della lista Squadre l’operatore in ritorna vero;

Arsiero non fa parte della lista e l’operazione in ritorna falso.
Possiamo usare not in combinazione con in per controllare se un elemento non

fa parte di una lista:

>>> ’Arsiero’ not in Squadre
1

Liste e cicli for
Il ciclo for si usa spesso anche con le liste. La

sintassi generica per il ciclo for in questo caso è: for VARIABILE in LISTA:

CORPO

Questa istruzione è equivalente a:

i=0
while i < len(LISTA):

VARIABILE = LISTA[i] CORPO
i=i+1

Il ciclo for è più conciso perché possiamo eliminare l’indice del ciclo i. Ecco il ciclo di uno degli esempi appena visti riscritto con il for:

for Squadra in Squadre:
  print Squadra

Si legge quasi letteralmente: “Per (ciascuna) Squadra in (nella lista di) Squadre, stampa (il nome della) Squadra”.

Nel ciclo for può essere usata qualsiasi espressione che produca una lista:

for Numero in range(20):
  if Numero % 2 == 0:

print Numero

for Frutto in ["banana", "mela", "pera"]:
  print "Mi piace la" + Frutto + "!"

Il primo esempio stampa tutti i numeri pari tra 0 e 19. Il secondo esprime l’entusiasmo per la frutta.

Operazioni sulle liste

L’operatore + concatena le liste:

>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> c = a + b
>>> print c

[1, 2, 3, 4, 5, 6]
L’operatore * ripete una lista un dato numero di volte:

[code lang=”objc”]
&lt;pre&gt;&gt;&gt;&gt; [0] * 4
[0, 0, 0, 0]
&gt;&gt;&gt; [1, 2, 3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
[/code]

Nel primo esempio abbiamo ripetuto [0] quattro volte. Nel secondo abbiamo ripetuto la lista [1, 2, 3] tre volte.

Porzioni di liste

Le porzioni che abbiamo già visto per le stringhe lavorano anche con le liste:

[code lang=”objc”]

&lt;pre&gt;&gt;&gt;&gt; Lista = [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]
&gt;&gt;&gt; Lista[1:3]
[’b’, ’c’]
&gt;&gt;&gt; Lista[:4]

[’a’, ’b’, ’c’, ’d’]
&gt;&gt;&gt; Lista[3:]
[’d’, ’e’, ’f’]
&gt;&gt;&gt; Lista[:]

[’a’, ’b’, ’c’, ’d’, ’e’, ’f’]
[/code]

Le liste sono mutabili

A differenza delle stringhe le liste sono mutabili e ciò significa che gli elementi possono essere modificati. Usando l’operatore porzione nella parte sinistra dell’assegnazione possiamo aggiornare un elemento:

[code lang=”objc”]

&lt;div&gt;
&lt;pre&gt;&gt;&gt;&gt; Frutta = [&quot;banana&quot;, &quot;mela&quot;, &quot;susina&quot;]
&gt;&gt;&gt; Frutta[0] = &quot;pera&quot;
&gt;&gt;&gt; Frutta[-1] = &quot;arancia&quot;
&gt;&gt;&gt; print Frutta

[’pera’, ’mela’, ’arancia’]
[/code]

Con l’operatore porzione possiamo modificare piu` elementi alla volta:

[code lang=”objc”]

&lt;pre&gt;&gt;&gt;&gt; Lista = [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]
&gt;&gt;&gt; Lista[1:3] = [’x’, ’y’]
&gt;&gt;&gt; print Lista
[’a’, ’x’, ’y’, ’d’, ’e’, ’f’]
[/code]

Possiamo rimuovere elementi da una lista assegnando loro una lista vuota:

[code lang=”objc”]

&lt;pre&gt;&gt;&gt;&gt; Lista = [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]
&gt;&gt;&gt; Lista[1:3] = []
&gt;&gt;&gt; print Lista
[’a’, ’d’, ’e’, ’f’]
[/code]

Possono essere aggiunti elementi ad una lista inserendoli in una porzione vuota nella posizione desiderata:

[code lang=”objc”]

&lt;pre&gt;&gt;&gt;&gt; Lista = [’a’, ’d’, ’f’]
&gt;&gt;&gt; Lista[1:1] = [’b’, ’c’]
&gt;&gt;&gt; print Lista
[’a’, ’b’, ’c’, ’d’, ’f’]
&gt;&gt;&gt; Lista[4:4] = [’e’]

&gt;&gt;&gt; print Lista
[’a’, ’b’, ’c’, ’d’, ’e’, ’f’]
[/code]

Cancellazione di liste

Usare le porzioni per cancellare elementi delle liste non è poi così pratico ed è facile sbagliare. Python fornisce un’alternativa molto più leggibile.

del rimuove un elemento da una lista:

[code lang=”objc”]

&lt;pre&gt;&gt;&gt;&gt; a = [’uno’, ’due’, ’tre’]
&gt;&gt;&gt; del a[1]
&gt;&gt;&gt; a
[’uno’, ’tre’]
[/code]

Come potete facilmente immaginare del gestisce anche gli indici negativi e avvisa con messaggio d’errore se l’indice è al di fuori dei limiti ammessi.

Potete usare una porzione come indice di del:

[code lang=”objc”]

&lt;pre&gt;&gt;&gt;&gt; Lista = [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]
&gt;&gt;&gt; del Lista[1:5]
&gt;&gt;&gt; print Lista
[’a’, ’f’]
[/code]

Come abbiamo già visto la porzione indica tutti gli elementi a partire dal primo indice incluso fino al secondo indice escluso.

Clonare le liste

Se vogliamo modificare una lista e mantenere una copia dell’originale dobbiamo essere in grado di copiare il contenuto della lista e non solo di creare un suo alias. Questo processo è talvolta chiamato clonazione per evitare l’ambiguità insita nella parola “copia”.Il modo piu` semplice per clonare una lista `e quello di usare l’operatore porzione:[code lang=”objc”]

&lt;pre&gt;&gt;&gt;&gt; a = [1, 2, 3]
&gt;&gt;&gt; b = a[:]
&gt;&gt;&gt; print b
[1, 2, 3]
[/code]

Il fatto di prendere una porzione di a crea una nuova lista. In questo caso la porzione consiste degli elementi dell’intera lista, dato che non sono stati specificati gli indici iniziale e finale.Ora siamo liberi di modificare b senza doverci preoccupare di a:

>>> b[0] = 5
>>> print a
[1, 2, 3]

Liste annidate

Una lista annidata è una lista che compare come elemento di un’altra lista. Nell’esempio seguente il quarto elemento della lista (ricorda che stiamo parlando dell’elemento numero 3 dato che il primo ha indice 0) è una lista:

>>> Lista = [“ciao”, 2.0, 5, [10, 20]]
Se stampiamo Lista[3] otteniamo [10, 20]. Per estrarre un elemento da una

lista annidata possiamo procedere in due tempi:

>>> Elemento = Lista[3]
>>> Elemento[0]
10

O possiamo combinare i due passi in un’unica istruzione:

>>> Lista[3][0]
10

L’operatore porzione viene valutato da sinistra verso destra così questa espressione ricava il quarto elemento (indice 3) di Lista ed essendo questo una lista ne estrae il primo elemento (indice 0).

Matrici

Le liste annidate sono spesso usate per rappresentare matrici.

>>> Matrice = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Matrice è una lista di tre elementi dove ciascuno è una riga della matrice.

Possiamo selezionare una singola riga nel solito modo:

>>> Matrice[1]
[4, 5, 6]

O estrarre una singola cella usando il doppio indice:

>>> Matrice[1][1]
5

Il primo indice seleziona la riga ed il secondo la colonna. Questo è un modo comune di rappresentare le matrici ma non è l’unico: una variante è quella di usare una lista di colonne invece che di righe. Vedremo in seguito un’alternativa completamente diversa quando avremo visto i dizionari.

Stringhe e liste

Due delle funzioni più utili nel modulo string hanno a che fare con le liste di stringhe. La funzione split spezza una stringa in una lista di parole singole, considerando un qualsiasi carattere di spazio bianco come punto di interruzione tra parole consecutive:

[code lang=”objc”]
&lt;pre&gt;&gt;&gt;&gt; import string
&gt;&gt;&gt; Verso = &quot;Nel mezzo del cammin…&quot;
&gt;&gt;&gt; string.split(Verso)
[’Nel’, ’mezzo’, ’del’, ’cammin…’]
[/code]

Può anche essere usato un argomento opzionale per specificare quale debba essere il delimitatore da considerare. In questo esempio usiamo la stringa el come delimitatore:

[code lang=”objc”]
&lt;pre&gt;&gt;&gt;&gt; string.split(Verso, ’el’)
[’N’, ’ mezzo d’, ’ cammin…’]
[/code]

Il delimitatore non appare nella lista.

La funzione join si comporta in modo inverso rispetto a split: prende una lista di stringhe e ne concatena gli elementi inserendo uno spazio tra ogni coppia:

[code lang=”objc”]
&lt;pre&gt;&gt;&gt;&gt; Lista = [’Nel’, ’mezzo’, ’del’, ’cammin…’]
&gt;&gt;&gt; string.join(Lista)
’Nel mezzo del cammin…’
[/code]

Come nel caso di split, join accetta un argomento opzionale che rappresenta il delimitatore da inserire tra gli elementi. Il delimitatore di default è uno spazio ma può essere cambiato:

>>> string.join(Lista, ’_’) ’Nel_mezzo_del_cammin…’

Anche per questa lezione è tutto ragazzi, alla prossima!