I dizionari in Python sono dei costrutti iterabili, questa caratteristica li rende particolarmente utili nelle operazioni che prevedono la selezione di valori specifici o la restituzione di valori compresi all’interno di intervalli. Quanto esposto diviene ancora più chiaro nel caso in cui i dizionari, e i valori che rappresentano, vengano utilizzati all’interno di cicli o nei costrutti condizionali.
Comprehension dei dizionari
La comprehension in Python è una procedura che consente di creare nuovi dizionari partendo da una sequenza di valori preesistenti; si tratta di un concetto particolarmente interessante perché può essere applicato anche ad altri costrutti iterabili come le liste e i set. Analizziamo il seguente esempio:
# Comprehension dei dizionari in Python
# risultato atteso: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49}
cmp = {x: x*x for x in range(8)}
print(cmp)
A livello sintattico la comprehension dei dizionari viene rappresentata da un’espressione delimitata da parentesi graffe nella quale una coppia composta da chiave e valore viene seguita da un’istruzione. Nell’esempio di codice mostrato abbiamo una sequenza numerica generata da un ciclo for che prevede un massimo di 8 iterazioni; ad ogni iterazione verrà prodotta una coppia di valori dove il primo è il valore iniziale, mentre il secondo è il risultato del primo moltiplicato per sé stesso.
In sostanza ci troviamo davanti ad una soluzione più immediata rispetto a quella che prevede la definizione iniziale di un dizionario vuoto, privo di valori, da popolare successivamente attraverso un ciclo for. Lo snippet proposto in precedenza rappresenta quindi un’alternativa ad un’espressione come la seguente:
# Popolare un dizionario con un ciclo for
cmp = {}
for x in range(8):
cmp[x] = x*x
print(cmp)
In questo secondo caso però il risultato atteso dal primo esempio verrebbe restituito soltanto una volta eseguita l’ultima iterazione del ciclo, l’output prodotto è infatti il seguente:
{0: 0}
{0: 0, 1: 1}
{0: 0, 1: 1, 2: 4}
{0: 0, 1: 1, 2: 4, 3: 9}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
La comprehension permette inoltre di filtrare i valori destinati alla generazione di un nuovo dizionario. A tal proposito potremmo riproporre il primo esempio mostrato prevedendo di sottoporre l’output ad una condizione: dovranno essere presi in considerazione soltanto i valori dispari compresi nell’intervallo considerato. Per far questo faremo ricorso al costrutto condizionale if che opererà il controllo richiesto (l’esclusione dei valori pari) applicando a ciascun valore l’operatore modulo ("%"):
# Filtrare i risultati nella Comprehension dei dizionari
# risultato atteso: {1: 1, 3: 9, 5: 25, 7: 49}
cmp = {x: x*x for x in range(8) if x%2 == 1}
print(cmp)
L’operatore modulo dividerà per 2 tutti i valori iniziali prodotti dal ciclo for, nel caso in cui questi non dovessero restituire alcun resto verranno automaticamente esclusi dalla sequenza che popola il dizionario.
Test di appartenenza sui dizionari
Dato che i dizionari rappresentano delle sequenze non ordinate di valori, potrebbe essere interessante verificare la presenza o meno di un valore specifico all’interno del dizionario corrente. Tale operazione prende il nome di test di appartenenza (o membership) e si basa sostanzialmente sull’applicazione della keyword "in" a carico di un dizionario. Al contrario è possibile eseguire il test opposto, cioè verificare che un determinato valore sia assente da un dizionario; in questo caso dobbiamo utilizzare però la clausola "not in". I test di appartenenza possono rivelarsi particolarmente utili nel caso in cui la composizione di un dizionario non sia nota o quando un dizionario presenta un gran numero di elementi.
Negli esempi seguenti vengono operate due diverse verifiche, la prima con lo scopo di sapere se il valore "3" sia presente nel dizionario:
# Verificare la presenza di un valore in un dizionario
# risultato atteso: "True"
dz = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49}
print(3 in dz)
La seconda per verificare che il valore "4" sia invece assente:
# Verificare l'assenza di un valore da un dizionario
# risultato atteso: "False"
dz = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49}
print(4 not in dz)
La prima espressione produrrà "True" come risultato, il valore "3" è infatti presente nel dizionario, per lo stesso motivo la seconda espressione restituirà "False", in quanto lo scopo dell’operazione è quello di verificare l’assenza del valore "4" che è invece presente.
Contare gli elementi di un dizionario
Un’altra verifica interessante potrebbe essere quella da effettuare a carico del numero di elementi che compongono un dizionario, procedura per la quale Python fornisce un’apposita funzione denominata all. Per mostrarne il funzionamento utilizzeremo un dizionario già noto:
# Conteggio degli elementi di un dizionario
# risultato atteso: "8"
dz = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49}
print(len(dz))
Il risultato atteso dall’esecuzione del codice sarà "8", tante quante sono le componenti del nostro dizionario in cui ciascun elemento è formato da un valore iniziale e dal risultato della sua moltiplicazione per sé stesso.
Estrarre chiavi e valori
Volendo estrarre le chiavi associate ai valori di un dizionario potremmo farlo tramite la funzione sorted, in questo modo:
# Estrarre le chiavi di un dizionario
# risultato atteso: [0, 1, 2, 3, 4, 5, 6, 7]
dz = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49}
print(sorted(dz))
Nel caso del nostro esempio le chiavi verranno rappresentate dai valori iniziali poi moltiplicati per sé stessi delle coppie di valori che compongono gli elementi del dizionario.
Per estrarre invece i valori, e non le chiavi, dovremo fare ricorso ad un semplice ciclo di iterazione, quest’ultimo sarà basato sulla keyword "in" che permetterà di verificare la presenza o meno di uno dei valori prodotti dal ciclo all’interno del dizionario. Il ciclo dovrà essere applicato in questo modo:
# Iterare i valori di un dizionario
dz = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49}
for x in dz:
print(dz[x])
così da ottenere un risultato come il seguente:
0
1
4
9
16
25
36
49