Video Corso Base di Python 3

17: I Dizionari

In questa lezione parleremo dell'ultimo tipo di dato della Serie, i Dizionari!

I dizionari sono un pó come le Liste che abbiamo visto nelle scorse puntate, ma a differenza delle Liste in cui a ciascun valore dell'elenco corrisponde un numero indice progressivo, quindi da 0 in su, nei Dizionari ad ogni valore è associato un indice particolare chiamato chiave, e siamo proprio noi a impostare questa chiave che potrà essere di un qualsiasi tipo di dato eccetto liste e altri dizionari.

Per ogni valore all'interno del Dizionario avremo quindi una coppia chiave-valore: più che considerarli come un tipo di dato in se, è bene considerare i Dizionari come una struttura di dati.

Si tratta sicuramente della tipologia più complessa rispetto a tutte quelle analizzate fin'ora!

Andiamo a fare un esempio pratico in modo da rendere l'idea da un punto di vista visivo; i Dizionari vengono definiti utilizzando parentesi graffe:

mio_dizionario = {"mia_chiave_uno": "mio_valore", "età": 24, 3.14: "pi_greco", "primi": [1, 2, 3, 5, 7]}

Quindi con questa azione abbiamo definito una struttura di dati, contenente quattro di quelle che abbiamo chiamato coppie chiave-valore, associate al nome "mio_dizionario".

>>> mio_dizionario
{"mia_chiave_uno": "mio_valore", "età": 24, 3.14: "pi_greco", "primi": [1, 2, 3, 5, 7]}

Come vedete abbiamo utilizzato diversi tipi di valori, stringhe, interi e liste, associati ciascuno ad una chiave univoca. Le chiavi nei Dizionari sono proprio il corrispettivo degli indici nelle Liste: usiamo le chiavi per richiamare i valori ad esse associati.

Per ottenere il valore associato alla chiave "mia_chiave_uno" facciamo in questo modo:

>>> mio_dizionario["mia_chiave_uno"]
'mio_valore'

Stesso discorso vale per tutti gli altri valori presenti, richiamabili tramite le loro chiavi. Proviamo a richiamare il valore associato alla chiave 3.14:

>>> mio_dizionario[3.14]
'pi_greco'

Per aggiungere una nuova coppia chiave-valore al nostro Dizionario facciamo in questa maniera:

>>> mio_dizionario["nuova_chiave"] = "nuovo_valore"

>>> mio_dizionario
{'mia_chiave_uno': 'mio_valore', 'età': 24, 3.14: 'pi_greco', 'primi': [1, 2, 3, 5, 7], 'nuova_chiave': 'nuovo_valore'}

Allo stesso modo possiamo sostituire il valore associato ad una chiave già presente nel dizionario:

>>> mio_dizionario["età"] = 99
>>> mio_dizionario
{'mia_chiave_uno': 'mio_valore', 'età': 99, 3.14: 'pi_greco', 'primi': [1, 2, 3, 5, 7], 'nuova_chiave': 'nuovo_valore'}

Facciamo ora una precisazione: a differenza delle Liste, in cui l'insieme di valori è un insieme ordinato, i Dizionari sono elenchi di valori non ordinati.

Python riconoscerà quindi due dizionari come uguali se questi conterranno le stesse coppie chiave-valore, anche se apparentemente non si trovano stesso ordine.

Per verificare se una chiave è presente o meno all'interno di un Dizionario possiamo utilizzare gli operatori in e not in:

>>> "età" in mio_dizionario
True

>>> "zen" in mio_dizionario
False

Per eliminare una coppia chiave-valore possiamo utilizzare l'istruzione del:

>>> del mio_dizionario["mia_chiave_uno"]
>>> mio_dizionario
{'età': 99, 3.14: 'pi_greco', 'primi': [1, 2, 3, 5, 7], 'nuova_chiave': 'nuovo_valore'}

Definiamo ora un nuovo Dizionario, chiamiamolo ita_eng e inseriamoci proprio valori tipici di un dizionario, ad esempio di un dizionario Italiano - Inglese:

ita_eng = {"ciao":"hello","arrivederci":"goodbye","uova":"eggs","gatto":"cat","arancia":"orange"}

Esistono tre metodi associati ai Dizionari che ci consentono di ottenere in output una Lista di tutte le chiavi presenti, o una Lista di tutti i valori presenti, o di entrambi allo stesso tempo.

Questi metodi sono il metodo keys(), il metodo values() e il metodo items(): vediamo un pó come utilizzarli:


Metodo keys()

Keys è letteralmente traducibile come "chiavi", ed è proprio il metodo che ci consente di ottenere una Lista di tutte le chiavi presenti. Quindi per ottenere una Lista di tutte le chiavi presenti nel nostro Dizionario ita_eng facciamo:

>>> ita_eng.keys()
dict_keys(['ciao', 'arrivederci', 'uova', 'gatto', 'arancia'])

Metodo values()

Values significa proprio valori; utilizziamo quindi questo metodo per ottenere una Lista di tutti i valori presenti. Per ottenere una Lista di tutti i valori nel nostro Dizionario facciamo quindi:

>>> ita_eng.values()
dict_values(['hello', 'goodbye', 'eggs', 'cat', 'orange'])

Metodo items()

Infine utilizziamo il metodo items() per ottenere una Lista di tutte le coppie chiavi-valore presenti.

>>> ita_eng.items()
dict_items([('ciao', 'hello'), ('arrivederci', 'goodbye'), ('uova', 'eggs'), ('gatto', 'cat'), ('arancia', 'orange')])

Utilizzando questi metodi, ció che ci viene restituito è da considerare come un oggetto di tipo "dict_keys", "dict_values", "dict_items"

Se abbiamo bisogno di una lista vera e propria possiamo utilizzare anche qui la nostra cara funzione list():

>>> parole_eng = list(ita_eng.keys())
>>> parole_eng
['ciao', 'arrivederci', 'uova', 'gatto', 'arancia']

Possiamo inoltre utilizzare questi metodi in combinazione con un ciclo for, ad esempio per far ciclare il nostro for per tutte le chiavi del dizionario facciamo:

>>> for chiave in ita_eng.keys():
...     print(chiave)
... 
ciao
arrivederci
uova
gatto
arancia

Ma cosa succederebbe qualora provassimo a richiamare un valore associato a una chiave che non esiste nel nostro Dizionario? Be come è facile intuire, otterremo un errore, in questo caso un'eccezzione "KeyError", che comporterà il crash del programma:

>>> ita_eng["birra"]
Traceback (most recent call last):
  File "stdin", line 1, in module
KeyError: 'birra'

Alcuni di voi a questo punto staranno sicuramente pensando: be abbiamo visto sia gli if e gli else, che i try ed except, perché non utilizzare quelle istruzioni in combo con gli operatori in e not in, per evitare il crash del programma?

Ad esempio:

>>> if "birra" in ita_eng.keys():
...     print(ita_eng["birra"])
... else:
...     print("Chiave non trovata!")
... 
Chiave non trovata!

Be, il metodo funziona, ma è piuttosto lungo e noioso, sopratutto una volta che sappiamo che i Dizionari dispongono di un metodo specifico, ideato proprio per situazioni come queste: il Metodo get().

Richiamiamo il metodo get() sul nostro Dizionario ita_eng e passiamoli proprio la chiave "birra":

>>> ita_eng.get("birra","Chiave non trovata, mi spiace!")
'Chiave non trovata, mi spiace!'

Proviamo anche a chiamare il metodo passandoli una chiave stavolta esistente:

>>> ita_eng.get("ciao","Chiave non trovata!!!")
'hello' 

Quindi ció che il metodo get() fa è restituirci un valore di default come una sorta di "paracadute d'emergenza", qualora la chiave richiesta non esista nel nostro Dizionario.

Parallelamente al metodo get(), ci saranno dei momenti in cui a seconda della complessità di ció che stiamo facendo, potremo avere la necessità di creare una coppia chiave valore qualora una chiave non sia già presente e associata a un valore nel Dizionario.

Mi spiego meglio: sempre restando sull'esempio precedente, supponiamo di voler verificare se è presente la chiave "birra" nel nostro Dizionario, che come sappiamo ora non è presente:

>>> ita_eng
{'ciao': 'hello', 'arrivederci': 'goodbye', 'uova': 'eggs', 'gatto': 'cat', 'arancia': 'orange'}

Ma diciamo che stavolta vogliamo aggiungerla al dizionario assieme alla traduzione e in maniera rapida!

Per fare questo possiamo usare il metodo setdefault():

>>> ita_eng.setdefault("birra", "beer")
"beer"

Quindi ció che setdefault() ha fatto è stato cercare la chiave "birra" all'interno del nostro dizionario "ita_eng", e visto che la chiave non esisteva ha creato una coppia chiave-valore col valore "beer" da noi passato.

>>> ita_eng
{'ciao': 'hello', 'arrivederci': 'goodbye', 'uova': 'eggs', 'gatto': 'cat', 'arancia': 'orange', 'birra': 'beer'}

Avremo anche in questo caso potuto creare un ciclo for, ma sarebbe stato piuttosto macchinoso e superfluo, una volta che si conosce il metodo setdefault().


Ricapitolando:

  • I Dizionari sono delle strutture di dati non ordinate, contenenti coppie (chiave:valore)
  • Sia Chiave che Valore sono scelti da noi in maniera arbitraria
  • Conoscendone la Chiave, possiamo modificare, richiamare o eliminare il valore associato
  • Usiamo i metodi keys(), values() e items() per ottenere rispettivamente gli elenchi delle chiavi, dei valori, o delle coppie chiave-valore
  • Il metodo get() ci consente di ottenere un messaggio di default qualora la chiave richiesta non esista, aggirando eventuali errori
  • Il metodo setdefault() ci permette invece di creare una coppia chiave-valore qualora la chiave passata non esista già

Menu della Serie