Parte I — Le basi
Capitolo 5 — Liste e dizionari
Una variabile sola tiene un valore. Ma spesso i dati arrivano in gruppo: i voti di una classe, la spesa della settimana, l'anagrafica di una persona. Per questi casi Leo ha due contenitori fondamentali, che userai in ogni programma di una certa dimensione: le liste e i dizionari.
Le liste: cose in fila
Una lista è una sequenza ordinata di valori, scritti tra parentesi quadre e separati da virgole. Gli elementi sono numerati a partire da zero; con le quadre prendi quello alla posizione che vuoi, e un indice negativo conta dalla fine:
variabile voti = [28, 30, 24]
scrivi(voti[0])
scrivi(voti[-1])28
24🦁 Curiosità — Perché si conta da zero
Non è un capriccio di Leo: in quasi tutti i linguaggi il primo elemento di una lista ha indice 0, non 1. Nel 1982 il grande informatico Edsger Dijkstra scrisse un breve e celebre appunto (siglato EWD831) per spiegare perché contare da zero rende i conti più puliti, soprattutto quando si lavora con gli intervalli. Una volta fattaci l'abitudine, tornare indietro sembra scomodo.
A differenza dei testi, le liste si possono modificare. Puoi cambiare un elemento, aggiungerne, toglierne:
variabile voti = [28, 30, 24]
voti[1] = 29
voti.aggiungi(27)
scrivi(voti)
scrivi(lunghezza(voti))
scrivi(27 in voti)
scrivi(somma(voti))[28, 29, 24, 27]
4
vero
108Qui vedi quattro operazioni molto comuni: voti[1] = 29 sostituisce il secondo elemento; voti.aggiungi(27) ne attacca uno in fondo; lunghezza(voti) conta gli elementi; 27 in voti controlla se un valore è presente (dà vero o falso); somma(voti) addiziona tutti i numeri. La parolina in è preziosa: la ritroverai nei cicli e nelle condizioni.
I metodi delle liste
Oltre ad aggiungi, le liste hanno diversi metodi per rimescolare e cercare:
variabile numeri = [3, 1, 2]
numeri.ordina()
scrivi(numeri)
numeri.inverti()
scrivi(numeri)
scrivi(numeri.trova(3))
numeri.rimuovi(3)
scrivi(numeri)
scrivi(numeri.estrai())
scrivi(numeri)[1, 2, 3]
[3, 2, 1]
0
[2, 1]
1
[2].ordina() mette in ordine (crescente di serie), .inverti() rovescia, .trova(x) dà la posizione del primo elemento uguale a x, .rimuovi(x) toglie la prima occorrenza di x, .estrai() toglie e restituisce l'ultimo elemento (o quello all'indice che indichi). Attenzione a una sottigliezza: questi metodi cambiano la lista sul posto e non restituiscono la lista modificata. Per questo scriviamo numeri.ordina() su una riga e poi scrivi(numeri) su un'altra, e non scrivi(numeri.ordina()) (che stamperebbe nulla). È il contrario dei metodi dei testi, che invece restituiscono sempre un valore nuovo; la ragione è proprio che i testi non si modificano e le liste sì.
I dizionari: cose con un'etichetta
In una lista ritrovi un valore sapendo la sua posizione. In un dizionario lo ritrovi sapendo la sua etichetta — che si chiama chiave. Un dizionario è un insieme di coppie «chiave → valore», scritte tra graffe:
💡 L'idea — Come una rubrica
Un dizionario funziona proprio come un vero dizionario di carta, o come la rubrica del telefono: non scorri tutte le pagine una per una. Vai diritto alla parola che cerchi — la chiave — e leggi la sua definizione, cioè il valore. È questa la differenza con la lista, dove a contare è invece la posizione.
variabile persona = {"nome": "Ada", "eta": 36}
scrivi(persona["nome"])
persona["citta"] = "Londra"
scrivi(persona.prendi("email", "-"))
scrivi(persona.ha("eta"))
per ogni chiave in persona fai
scrivi "{chiave}: {persona[chiave]}"
fineAda
-
vero
nome: Ada
eta: 36
citta: LondraCon le quadre e la chiave leggi un valore (persona["nome"]) e, assegnando a una chiave nuova, la aggiungi (persona["citta"] = "Londra"). Ma cosa succede se chiedi una chiave che non esiste? persona["email"] darebbe un errore (ErroreChiave). Per questo esistono due vie sicure: .prendi(chiave, predefinito) restituisce il valore o, se la chiave manca, il valore di riserva che indichi (qui "-"); e .ha(chiave) dice semplicemente se la chiave c'è. Infine, un ciclo per ogni chiave in persona scorre tutte le chiavi: lo vedremo nel dettaglio nel prossimo capitolo.
Le chiavi di un dizionario sono di solito testi, ma possono anche essere interi o valori logici. I valori, invece, possono essere qualunque cosa: numeri, testi, altre liste, altri dizionari. Annidando liste e dizionari si rappresentano dati anche molto ricchi — pensa a una rubrica, dove ogni contatto è un dizionario e tutti i contatti stanno in una lista.
Costruire liste in una riga
Capita spesso di voler costruire una lista calcolando ogni elemento a partire da un'altra sequenza. Leo ha una forma compatta ed elegante per farlo, la comprensione di lista:
variabile quadrati = [n * n per ogni n in 1..5]
scrivi(quadrati)
variabile pari = [n per ogni n in 1..10 se n % 2 == 0]
scrivi(pari)[1, 4, 9, 16, 25]
[2, 4, 6, 8, 10]Si legge quasi come una frase: «n * n, per ogni n da 1 a 5» costruisce la lista dei quadrati; e aggiungendo una condizione se tieni solo gli elementi che vuoi — qui i numeri pari da 1 a 10. È una scrittura che condensa in una riga quello che altrimenti richiederebbe un ciclo di tre o quattro. All'inizio può sembrare densa; con un po' di pratica diventa una delle cose che renderanno i tuoi programmi più leggibili.
(Hai notato 1..5 e 1..10? Sono intervalli: un modo breve per dire «tutti i numeri da qui a lì». Li incontreremo di nuovo, da protagonisti, nel prossimo capitolo.)
Prova tu
- Parti da una lista della spesa con quattro voci. Aggiungine una, togline una, ordina la lista in ordine alfabetico e stampa quante voci sono rimaste.
- Costruisci un dizionario che descrive un libro (titolo, autore, anno), poi stampalo in una frase sola usando l'interpolazione. Aggiungi la chiave
paginee ristampalo. - Usando una comprensione, costruisci la lista dei multipli di 3 da 1 a 30. Poi modificala perché tenga solo quelli che sono anche multipli di 2.