2.8. Introduzione alle liste

Le liste sono, tra i tipi di dati in Python, la vera forza motrice. Se la vostra sola esperienza con le liste sono gli array in Visual Basic o (Dio ve ne scampi!) il datastore di Powerbuilder, fatevi forza e osservate come si usano in Python.

Nota
Una lista in Python è come un array in Perl. In Perl, le variabili che contengono array hanno un nome che inizia sempre con il carattere @; in Python le variabili possono avere qualunque nome, è il linguaggio che tiene traccia internamente del tipo di dato.
Nota
Una lista in Python è molto più di un array in Java (sebbene possa essere usato allo stesso modo, se davvero non volete altro). Un'analogia migliore sarebbe la classe Vector, che può contenere oggetti di tipo arbitrario e si espande automaticamente quando vi si aggiungono nuovi elementi.

Esempio 2.15. Definire una lista

>>> li = ["a", "b", "mpilgrim", "z", "example"] 1
>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li[0]                                       2
'a'
>>> li[4]                                       3
'example'
1 Per prima cosa definiamo una lista di 5 elementi. Notate che questi mantengono l'ordine d'inserimento, in quanto una lista e' un insieme ordinato di elementi racchiusi tra parentesi quadrate.
2 A differenza di altri linguaggi, Python non permette di scegliere se gli array cominciano con l'elemento 0 oppure 1. Se la lista non è vuota, il primo elemento si indica sempre con li[0].
3 In questa lista di 5 elementi, l'ultimo si indica con li[4] perché le liste hanno sempre base zero.

Esempio 2.16. Indici di liste negativi

>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li[-1] 1
'example'
>>> li[-3] 2
'mpilgrim'
1 Un indice negativo accede agli elementi a partire dalla fine della lista, contando all'indietro. L'ultimo elemento di una lista non vuota è sempre li[-1].
2 Se gli indici negativi vi confondono, pensate in questo modo: li[-n] == li[len(li) - n]. Così, in questa lista, li[-3] == li[5 - 3] == li[2].

Esempio 2.17. Sezionare una lista.

>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li[1:3]  1
['b', 'mpilgrim']
>>> li[1:-1] 2
['b', 'mpilgrim', 'z']
>>> li[0:3]  3
['a', 'b', 'mpilgrim']
1 Potete estrarre una sezione di una lista, chiamata “slice”, (fetta), specificandone i due estremi. Il valore della sezione è una nuova lista, contenente tutti gli elementi, nello stesso ordine, dal primo indice (in questo caso li[1]), fino al secondo indice escluso (in questo caso li[3]).
2 Il sezionamento, o slicing, funziona anche se uno o entrambi gli indici sono negativi. Potete pensarla in questo modo: leggendo la lista da sinistra a destra, il primo indice specifica il primo elemento che volete, mentre il secondo specifica il primo elemento che non volete. Il valore ritornato è una lista degli elementi che stanno in mezzo.
3 Gli elementi della lista si contano da zero, così li[0:3] ritorna i primi tre elementi della lista, partendo da li[0] fino a li[3] escluso.

Esempio 2.18. Sezionamento abbreviato

>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li[:3] 1
['a', 'b', 'mpilgrim']
>>> li[3:] 2 3
['z', 'example']
>>> li[:]  4
['a', 'b', 'mpilgrim', 'z', 'example']
1 Se l'indice di sinistra è 0, potete non indicarlo e lo 0 è sottinteso. In questo caso li[:3] è identico a li[0:3] dell'esempio precedente.
2 Allo stesso modo, se l'indice destro è pari alla lunghezza della lista, potete lasciarlo sottinteso. Così li[3:] è identico a li[3:5], perché la lista ha 5 elementi.
3 Notate la simmetria. In questa lista di 5 elementi, li[:3] ritorna i primi 3, mentre li[3:] ritorna gli ultimi 2 elementi. Di fatto, li[:n] ritornerà sempre i primi n elementi e li[n:] ritornerà la parte restante della lista a prescindere dalla lunghezza di quest'ultima.
4 Se chiedete un sezionamento senza specificare alcun indice, tutti gli elementi della lista saranno inclusi. L'oggetto restituito però non è la lista li originale; è una nuova lista che contiene gli stessi elementi. li[:] è un'abbreviazione per creare una copia completa di una lista.

Esempio 2.19. Aggiungere elementi ad una lista

>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li.append("new")               1
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new']
>>> li.insert(2, "new")            2
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new']
>>> li.extend(["two", "elements"]) 3
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
1 append aggiunge un singolo elemento alla fine della lista.
2 insert inserisce un singolo elemento in una posizione specifica della lista. L'argomento numerico è l'indice del primo elemento che verrà spostato nella posizione successiva. Notate che gli elementi di una lista non devono necessariamente essere unici; adesso ci sono 2 elementi distinti con il valore 'new', li[2] e li[6].
3 extend concatena due liste. Notate che non si può chiamare extend con argomenti multipli: l'unico argomento accettato è una lista. In questo caso la lista ha due elementi.

Esempio 2.20. Ricerca in una lista

>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
>>> li.index("example") 1
5
>>> li.index("new")     2
2
>>> li.index("c")       3
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
ValueError: list.index(x): x not in list
>>> "c" in li           4
0
1 index cerca la prima presenza di un valore nella lista e ne ritorna l'indice.
2 index cerca la prima presenza di un valore nella lista. In questo caso, 'new' compare due volte nella lista, in li[2] e li[6], ma index ritorna solamente il primo indice, 2.
3 Se il valore non è presente nella lista, Python solleva un'eccezione. Questo comportamento è diverso dalla maggior parte dei linguaggi, in cui viene ritornato qualche valore di indice non valido. Per quanto il lancio di un'eccezione possa sembrare seccante, in realtà è meglio così perché il vostro programma vi indicherà la radice del problema, anziché bloccarsi più tardi quando cercherete di usare l'indice non valido.
4 Per controllare se un valore è nella lista usate l'operatore in, che ritorna 1 se il valore è presente e 0 in caso contrario.
Nota
Prima della versione 2.2.1, Python non aveva un tipo di dato booleano distinto dai numeri interi. Per compensare, Python accettava quasi tutto in un contesto booleano (come un comando if), secondo la seguente regola: 0 è falso; tutti gli altri numeri sono veri. Una stringa vuota ("") è falsa; tutte le altre stringhe sono vere. Una lista vuota ([]) è falsa; tutte le altre liste sono vere. Una tupla vuota (()) è falsa; tutte le altre tuple sono vere. Un dizionario vuoto ({}) è falso; tutti gli altri dizionari sono veri. Queste regole valgono ancora in Python 2.2.1 e oltre, ma ora si può usare anche un valore booleano vero e proprio, che ha valore True o False. Notate le maiuscole; questi valori, come tutto il resto in Python, sono case-sensitive.

Esempio 2.21. Togliere elementi da una lista

>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
>>> li.remove("z")   1
>>> li
['a', 'b', 'new', 'mpilgrim', 'example', 'new', 'two', 'elements']
>>> li.remove("new") 2
>>> li
['a', 'b', 'mpilgrim', 'example', 'new', 'two', 'elements']
>>> li.remove("c")   3
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
ValueError: list.remove(x): x not in list
>>> li.pop()         4
'elements'
>>> li
['a', 'b', 'mpilgrim', 'example', 'new', 'two']
1 remove toglie la prima presenza di un valore nella lista.
2 remove toglie solo la prima ricorrenza di un valore specificato. In questo caso, 'new' compare due volte nella lista, ma li.remove("new") ha tolto solo il primo elemento che ha trovato.
3 Se il valore non è presente nella lista, Python solleva un'eccezione. Questo comportamento rispecchia quello del metodo index.
4 pop è un animale interessante. Fa due cose: toglie l'ultimo elemento della lista e ne ritorna il valore. Notate che ciò è diverso da li[-1], che ritorna un valore ma non cambia la lista ed è diverso anche da li.remove(valore), che cambia la lista ma non ritorna un valore.

Esempio 2.22. Operatori su liste

>>> li = ['a', 'b', 'mpilgrim']
>>> li = li + ['example', 'new'] 1
>>> li
['a', 'b', 'mpilgrim', 'example', 'new']
>>> li += ['two']                2
>>> li
['a', 'b', 'mpilgrim', 'example', 'new', 'two']
>>> li = [1, 2] * 3              3
>>> li
[1, 2, 1, 2, 1, 2]
1 Le liste possono anche essere concatenate con l'operatore +. lista = lista + altralista ha lo stesso risultato di lista.extend(altralista), ma l'operatore + ritorna una nuova lista (concatenata) come valore, mentre extend modifica la lista già esistente. Pertanto, extend è più veloce, in modo particolare in riferimento a grandi liste.
2 Python supporta l'operatore +=. li += ['two'] equivale a li.extend(['two']). L'operatore += funziona con liste, stringhe ed interi e può essere aggiunto alle classi create dal programmatore. (Per le classi, vedi il capitolo 3.)
3 L'operatore * ripete gli elementi di una lista. li = [1, 2] * 3 è uguale a li = [1, 2] + [1, 2] + [1, 2], che concatena le tre liste in una sola.

Ulteriori letture