Dizionari Python
Impara i dizionari Python: crea, accedi, aggiorna, elimina, itera e usa le comprehension con esempi chiari e gli errori più comuni.
Un dizionario Python è una collezione mutabile e ordinata di coppie chiave-valore. A differenza delle liste o delle tuple (che usano posizioni intere), un dizionario ti permette di etichettare ogni valore con una chiave significativa — rendendo le ricerche veloci e il codice più leggibile. I dizionari sono uno dei tipi built-in più utilizzati in Python e sono alla base della gestione di JSON, della configurazione, del conteggio delle parole e molto altro.
Questo capitolo copre tutto ciò che devi sapere per usare i dizionari con sicurezza: creazione, accesso, modifica, eliminazione, iterazione, comprehension e gli errori più comuni.
Capitoli correlati: Metodi dei Dizionari | Dizionari Annidati | Cicli sui Dizionari | Copiare i Dizionari | Comprehension Python
Cos'è un Dizionario?
Un dizionario associa chiavi uniche e hashable a valori di qualsiasi tipo. La regola fondamentale: le chiavi devono essere immutabili — string, numeri e tuple di immutabili sono tutti validi; liste e altri dizionari non lo sono.
# string keys → integer values
inventory = {'apple': 10, 'banana': 5, 'orange': 8}
# mixed value types are fine
person = {'name': 'Alice', 'age': 30, 'active': True}
# tuple keys work because tuples are immutable
grid = {(0, 0): 'origin', (1, 0): 'east', (0, 1): 'north'}A partire da Python 3.7, i dizionari mantengono l'ordine di inserimento — iterare su un dizionario restituisce sempre le chiavi nell'ordine in cui sono state aggiunte.
Creare un Dizionario
Letterale con parentesi graffe
Il modo più comune: separare le coppie chiave-valore con virgole, usare i due punti tra ogni chiave e il suo valore, e racchiudere il tutto in {}.
config = {'host': 'localhost', 'port': 5432, 'debug': True}
print(config)
# {'host': 'localhost', 'port': 5432, 'debug': True}Un dizionario vuoto è semplicemente {}.
empty = {}
print(type(empty)) # <class 'dict'>Costruttore dict()
Passa argomenti keyword a dict() quando le tue chiavi sono identificatori Python validi:
config = dict(host='localhost', port=5432, debug=True)
print(config)
# {'host': 'localhost', 'port': 5432, 'debug': True}Puoi anche passare un iterabile di sequenze a due elementi:
pairs = [('x', 10), ('y', 20)]
point = dict(pairs)
print(point) # {'x': 10, 'y': 20}dict.fromkeys()
Crea un dizionario da una lista di chiavi, tutte condividendo lo stesso valore iniziale:
defaults = dict.fromkeys(['timeout', 'retries', 'verbose'], 0)
print(defaults)
# {'timeout': 0, 'retries': 0, 'verbose': 0}Attenzione: se il valore predefinito è un oggetto mutabile (come una lista), tutte le chiavi condivideranno lo stesso oggetto. Usa invece una dictionary comprehension (mostrata sotto).
Dictionary comprehension
Un modo conciso per costruire un dizionario da qualsiasi iterabile:
squares = {x: x ** 2 for x in range(1, 6)}
print(squares)
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}Vedi Comprehension Python per la sintassi completa.
Accedere ai Valori
Ricerca con parentesi quadre
inventory = {'apple': 10, 'banana': 5, 'orange': 8}
print(inventory['apple']) # 10Se la chiave non esiste, Python solleva un KeyError:
try:
print(inventory['grape'])
except KeyError as e:
print(f'KeyError: {e}') # KeyError: 'grape'get() — ricerca sicura con valore predefinito
dict.get(key, default) restituisce il valore se la chiave esiste, oppure default (che è None se omesso) altrimenti — senza sollevare eccezioni.
print(inventory.get('grape')) # None
print(inventory.get('grape', 0)) # 0
print(inventory.get('apple', 0)) # 10Usa .get() ogni volta che non sei sicuro che una chiave esista. Usa la ricerca con parentesi quadre quando la chiave deve essere presente — una chiave mancante è allora un vero bug che dovrebbe emergere come errore.
Verificare se una chiave esiste
print('apple' in inventory) # True
print('grape' in inventory) # False
print('grape' not in inventory) # Truein controlla le chiavi, non i valori. Viene eseguito in tempo O(1) medio — costante, indipendentemente dalla dimensione del dizionario.
Aggiungere e Aggiornare Elementi
Aggiungere una nuova coppia chiave-valore
Assegna a una chiave che non esiste ancora:
inventory['grape'] = 12
print(inventory)
# {'apple': 10, 'banana': 5, 'orange': 8, 'grape': 12}Aggiornare un valore esistente
Assegna a una chiave che esiste già — il vecchio valore viene sostituito:
inventory['apple'] = 15
print(inventory['apple']) # 15update() — aggiunta o sovrascrittura in blocco
Passa un altro dizionario o un iterabile di coppie chiave-valore:
inventory.update({'banana': 7, 'mango': 3})
print(inventory)
# {'apple': 15, 'banana': 7, 'orange': 8, 'grape': 12, 'mango': 3}Unione con | (Python 3.9+)
L'operatore | crea un nuovo dizionario unito. Se una chiave appare in entrambi, vince il lato destro:
a = {'x': 1, 'y': 2}
b = {'y': 99, 'z': 3}
merged = a | b
print(merged) # {'x': 1, 'y': 99, 'z': 3}Usa |= per unire b in a sul posto — equivalente a a.update(b) ma più leggibile.
setdefault() — inserisci solo se assente
dict.setdefault(key, default) inserisce la chiave con il valore predefinito se è assente, poi restituisce sempre il valore per quella chiave. Questo è più efficiente del pattern if key not in d: d[key] = default.
scores = {'Alice': 95}
scores.setdefault('Bob', 0) # Bob absent → inserts 0, returns 0
scores.setdefault('Alice', 0) # Alice present → does nothing, returns 95
print(scores) # {'Alice': 95, 'Bob': 0}Un caso d'uso classico è raggruppare elementi:
words = ['cat', 'car', 'bus', 'can', 'bat']
groups = {}
for word in words:
groups.setdefault(word[0], []).append(word)
print(groups)
# {'c': ['cat', 'car', 'can'], 'b': ['bus', 'bat']}Rimuovere Elementi
del — rimuovi per chiave
inventory = {'apple': 15, 'banana': 7, 'orange': 8, 'grape': 12}
del inventory['orange']
print(inventory)
# {'apple': 15, 'banana': 7, 'grape': 12}del solleva KeyError se la chiave è assente. Per evitarlo, controlla prima con in, oppure usa pop() con un valore predefinito.
pop() — rimuovi e restituisci il valore
removed = inventory.pop('grape')
print(removed) # 12
print(inventory) # {'apple': 15, 'banana': 7}Fornisci un secondo argomento per evitare KeyError quando la chiave potrebbe essere assente:
val = inventory.pop('pear', 'not found')
print(val) # not foundpopitem() — rimuovi l'ultimo elemento inserito (Python 3.7+)
d = {'a': 1, 'b': 2, 'c': 3}
last = d.popitem()
print(last) # ('c', 3)
print(d) # {'a': 1, 'b': 2}clear() — rimuovi tutto
d = {'a': 1, 'b': 2}
d.clear()
print(d) # {}Iterare su un Dizionario
Tre viste consentono di iterare su diverse parti di un dizionario. Tutte e tre sono viste live — riflettono le modifiche al dizionario senza dover essere ricreate.
Chiavi (iterazione predefinita)
Iterare direttamente su un dizionario restituisce le sue chiavi:
person = {'name': 'Alice', 'age': 30, 'city': 'Paris'}
for key in person:
print(key)
# name
# age
# cityperson.keys() restituisce le stesse chiavi come oggetto vista dict_keys esplicito.
Valori
for val in person.values():
print(val)
# Alice
# 30
# ParisCoppie chiave-valore
for key, val in person.items():
print(f'{key}: {val}')
# name: Alice
# age: 30
# city: Paris.items() è la scelta più comune quando hai bisogno sia della chiave che del valore all'interno del ciclo. Vedi Cicli sui Dizionari per pattern avanzati.
Le viste sono live
d = {'a': 1}
keys_view = d.keys()
d['b'] = 2
print(keys_view) # dict_keys(['a', 'b']) ← reflects the new keyDictionary Comprehension
Le dictionary comprehension permettono di costruire o trasformare dizionari in un'unica espressione leggibile.
Filtrare per valore
inventory = {'apple': 15, 'banana': 7, 'orange': 8, 'grape': 12, 'mango': 3}
popular = {k: v for k, v in inventory.items() if v >= 8}
print(popular)
# {'apple': 15, 'orange': 8, 'grape': 12}Invertire un dizionario (scambiare chiavi e valori)
original = {'a': 1, 'b': 2, 'c': 3}
swapped = {v: k for k, v in original.items()}
print(swapped) # {1: 'a', 2: 'b', 3: 'c'}Questo funziona in modo sicuro solo quando tutti i valori sono unici.
Contatore di frequenza delle parole
sentence = 'the quick brown fox jumps over the lazy dog'
freq = {}
for word in sentence.split():
freq[word] = freq.get(word, 0) + 1
print(freq)
# {'the': 2, 'quick': 1, 'brown': 1, 'fox': 1, ...}Funzioni Built-in Utili
| Operazione | Esempio | Risultato |
|---|---|---|
| Lunghezza | len(inventory) | numero di coppie chiave-valore |
| Copia (superficiale) | inventory.copy() | nuovo dict, stesse riferimenti |
| Converti in lista di chiavi | list(inventory) | ['apple', 'banana', ...] |
| Chiavi ordinate | sorted(inventory) | ['apple', 'banana', ...] in ordine alfabetico |
| Tutti i valori veri? | all(inventory.values()) | True / False |
| Almeno un valore vero? | any(inventory.values()) | True / False |
Per un riferimento completo di tutti i metodi dei dizionari (copy, fromkeys, update, setdefault, popitem e altri), vedi Metodi dei Dizionari Python.
Errori Comuni
1. KeyError su chiave mancante — usa sempre .get() o in quando una chiave potrebbe non esistere.
2. Tipi di chiave non hashable — le liste non possono essere chiavi di dizionario perché sono mutabili. Usa una tupla al posto:
# This raises TypeError: unhashable type: 'list'
# bad = {[1, 2]: 'value'}
# Use a tuple:
coords = {(1, 2): 'A', (3, 4): 'B'}
print(coords[(1, 2)]) # A3. Modifica durante l'iterazione — aggiungere o rimuovere chiavi mentre si itera su un dizionario solleva RuntimeError. Fai prima uno snapshot:
d = {'a': 1, 'b': 2, 'c': 3}
for key in list(d): # list() copies the keys
if d[key] < 2:
del d[key]
print(d) # {'b': 2, 'c': 3}4. Copia superficiale vs. copia profonda — dict.copy() e {**d} effettuano entrambi una copia superficiale. I valori mutabili annidati (liste, dizionari) sono ancora condivisi. Usa copy.deepcopy() quando hai bisogno di copie completamente indipendenti. Vedi Copiare i Dizionari.
Dizionari vs. Altri Tipi di Collezione
| Caratteristica | dict | list | tuple | set |
|---|---|---|---|---|
| Ordinato | Sì (3.7+) | Sì | Sì | No |
| Mutabile | Sì | Sì | No | Sì |
| Indicizzato per | Chiave | Intero | Intero | — |
| Duplicati | Chiavi: no; Valori: sì | Sì | Sì | No |
| Utilizzo principale | Mappatura chiave-valore | Sequenza ordinata | Sequenza immutabile | Unicità / operazioni sugli insiemi |
Quando hai bisogno di cercare qualcosa tramite un'etichetta significativa anziché una posizione, un dizionario è quasi sempre la scelta giusta. Per valori unici ordinati, considera un set. Per una semplice sequenza ordinata, usa una list.