La classe dict di Python fornisce molti metodi utili per lavorare con i dizionari.
Alcuni sono già stati introdotti nel concetto dedicato ai dict.
Qui ne vediamo altri, insieme ad alcune tecniche per iterare sui dizionari e modificarli.
<dict>.setdefault() aggiunge chiavi automaticamente senza sollevare un KeyError.<dict>.fromkeys(<iterable>, <default value>) crea un nuovo dict a partire da un numero qualsiasi di iterabili.<dict>.keys(), <dict>.values() e <dict>.items() forniscono iteratori comodi.sorted(<dict>.items()) può facilmente riordinare le voci di un dict.<dict_one>.update(<dict_two>) aggiorna un dict con i valori sovrapposti provenienti da un altro dict.<dict> | <other_dict> e <dict> |= <other_dict> uniscono o aggiornano due dict tramite operatori.reversed(<dict>.keys()), reversed(<dict>.values()) o reversed(<dict>.items()) producono viste invertite.<dict>.popitem() rimuove e restituisce una coppia key, value.setdefault() per un inserimento senza erroriIl concetto sui dizionari ha già visto che <dict>.get(<key>, <default value>) restituisce un value esistente oppure il default value se una key non è presente nel dizionario, evitando così un KeyError.
Funziona bene nelle situazioni in cui preferisci non avere una gestione degli errori aggiuntiva, ma non puoi dare per scontato che la key che cerchi sia presente.
Per un'operazione di inserimento altrettanto «sicura» (senza KeyError), esiste il metodo <dict>.setdefault(<key>, <default value>).
<dict>.setdefault(<key>, <default value>) restituisce il value se la key è presente nel dizionario.
Se la chiave non è presente, inserisce la coppia (key, default value) e restituisce il default value da usare.
>>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'}
# Looking for the value associated with key "Rock Brown".The key does not exist,
# so it is added with the default value, and the value is returned.
>>> palette.setdefault('Rock Brown', '#694605')
'#694605'
# The (key, default value) pair has now been added to the dictionary.
>>> palette_I
{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Rock Brown': '#694605'}
fromkeys() per popolare un dizionario da un iterabilePer popolare rapidamente un dizionario con varie keys e valori predefiniti, il metodo di classe fromkeys(<iterable>, <default value>) itera su un iterabile di keys e crea un nuovo dict.
Tutti i values vengono impostati al default value fornito:
>>> new_dict = dict.fromkeys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'], 'fill in hex color here')
{'Grassy Green': 'fill in hex color here',
'Purple Mountains Majesty': 'fill in hex color here',
'Misty Mountain Pink': 'fill in hex color here'}
.popitem()
.popitem() rimuove e restituisce una singola coppia (key, value) da un dizionario.
Le coppie vengono restituite in ordine Last-in-First-out (LIFO).
Se il dizionario è vuoto, chiamare popitem() solleva un KeyError:
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
>>> palette_I.popitem()
('Misty Mountain Pink', '#f9c5bd')
>>> palette_I.popitem()
('Purple Mountains Majesty', '#8076a3')
>>> palette_I.popitem()
('Grassy Green', '#9bc400')
# All (key, value) pairs have been removed.
>>> palette_I.popitem()
Traceback (most recent call last):
line 1, in <module>
palette_I.popitem()
KeyError: 'popitem(): dictionary is empty'
I metodi .keys(), .values() e .items() restituiscono viste iterabili di un dizionario.
Queste viste permettono di scorrere facilmente le voci senza modificarle.
Le viste sono anche dinamiche: quando i dati sottostanti del dizionario cambiano, il view object associato riflette il cambiamento:
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
# Using .keys() returns a list of keys.
>>> palette_I.keys()
dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'])
# Using .values() returns a list of values.
>>> palette_I.values()
dict_values(['#9bc400', '#8076a3', '#f9c5bd'])
# Using .items() returns a list of (key, value) tuples.
>>> palette_I.items()
dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', '#8076a3'), ('Misty Mountain Pink', '#f9c5bd')])
# Views are dynamic. Changing values in the dict
# changes all of the associated views.
>>> palette_I['Purple Mountains Majesty'] = (128, 118, 163)
>>> palette_I['Deep Red'] = '#932432'
>>> palette_I.values()
dict_values(['#9bc400', (128, 118, 163), '#f9c5bd', '#932432'])
>>> palette_I.keys()
dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink', 'Deep Red'])
>>> palette_I.items()
dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', (128, 118, 163)), ('Misty Mountain Pink', '#f9c5bd'), ('Deep Red', '#932432')])
.keys(), .values() e .items()
In Python 3.7+, i dict mantengono l'ordine di inserimento delle voci, il che consente un'iterazione First-in, First-out (FIFO) quando usi .keys(), .values() o .items().
In Python 3.8+, le viste sono anche reversibili.
Questo permette di iterare su chiavi, valori o coppie (key, value) in ordine Last-in, First-out (LIFO) usando reversed(<dict>.keys()), reversed(<dict>.values()) o reversed(<dict>.items()):
>>> palette_II = {'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
>>> for item in palette_II.items():
... print(item)
...
('Factory Stone Purple', '#7c677f')
('Green Treeline', '#478559')
('Purple baseline', '#161748')
>>> for item in reversed(palette_II.items()):
... print(item)
...
('Purple baseline', '#161748')
('Green Treeline', '#478559')
('Factory Stone Purple', '#7c677f')
.update()
<dict_one>.update(<dict_two>) può essere usato per combinare due dizionari.
Questo metodo prende le coppie (key,value) di <dict_two> e le scrive in <dict_one>:
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
>>> palette_II = {'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple Baseline': '#161748'}
>>> palette_I.update(palette_II)
# Note that new items from palette_II are added.
>>> palette_I
{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple Baseline': '#161748'}
Quando le chiavi dei due dizionari si sovrappongono, il value in dict_one viene sovrascritto dal value corrispondente di dict_two:
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
>>> palette_III = {'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189)}
>>> palette_I.update(palette_III)
# Overlapping values in palette_I are replaced with
# values from palette_III
>>> palette_I
{'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189),
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559', 'Purple baseline': '#161748'}
| e |=)Python 3.9 introduce un modo diverso di unire i dict: gli operatori di union.
dict_one | dict_two crea un nuovo dizionario, formato dalle coppie (key, value) di dict_one e dict_two.
Quando entrambi i dizionari condividono delle chiavi, i valori di dict_two hanno la precedenza.
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
>>> palette_II = {'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
>>> new_dict = palette_I | palette_II
>>> new_dict
...
{'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
dict_one |= other si comporta in modo simile a <dict_one>.update(<other>), ma in questo caso other può essere un dict oppure un iterabile di coppie (key, value):
>>> palette_III = {'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189)}
>>> new_dict |= palette_III
>>> new_dict
...
{'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189),
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
I dizionari non hanno un metodo di ordinamento integrato.
Tuttavia, è possibile ordinare una vista di un dict usando la funzione integrata sorted() insieme a .items().
La vista ordinata può poi essere usata per creare un nuovo dizionario.
Se non viene specificata una chiave di ordinamento, l'ordinamento predefinito avviene sulle keys del dizionario.
# Default ordering for a dictionary is last in, first out (LIFO).
>>> color_palette = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
# The default sort order for a dictionary uses the keys.
>>> sorted_palette = dict(sorted(color_palette.items()))
>>> sorted_palette
{'Factory Stone Purple': '#7c677f',
'Grassy Green': '#9bc400',
'Green Treeline': '#478559',
'Misty Mountain Pink': '#f9c5bd',
'Purple Mountains Majesty': '#8076a3',
'Purple baseline': '#161748'}
# A sort key can be provided in the form
# of an anonymous function (lambda).
>>> value_sorted_palette = dict(sorted(color_palette.items(), key=lambda color: color[1]))
>>> value_sorted_palette
{'Purple baseline': '#161748',
'Green Treeline': '#478559',
'Factory Stone Purple': '#7c677f',
'Purple Mountains Majesty': '#8076a3',
'Grassy Green': '#9bc400',
'Misty Mountain Pink': '#f9c5bd'}
Scambiare chiavi e valori in modo affidabile in un dizionario richiede un po' di lavoro, ma si può fare con un loop che usa dict.items() oppure con una comprensione di dizionario.
Uno scambio sicuro presuppone che sia le chiavi sia i valori del dicts siano hashable.
color_reference = {'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
# Creating a new dictionary to hold the swapped entries.
>>> swapped_color_reference = {}
# Iterating through the dictionary, using values as keys.
>>> for key, value in color_reference.items():
... swapped_color_reference[value] = key
>>> swapped_color_reference
{'#8076a3': 'Purple Mountains Majesty',
'#f9c5bd': 'Misty Mountain Pink',
'#7c677f': 'Factory Stone Purple',
'#478559': 'Green Treeline',
'#161748': 'Purple baseline'}
# A dictionary comprehension can also be used to swap entries.
>>> swapped = {value: key for key, value in
color_reference.items()}
>>> swapped
{'#8076a3': 'Purple Mountains Majesty',
'#f9c5bd': 'Misty Mountain Pink',
'#7c677f': 'Factory Stone Purple',
'#478559': 'Green Treeline',
'#161748': 'Purple baseline'}
Se i valori memorizzati nel dicts non sono unici, servono controlli aggiuntivi prima di poter scambiare chiavi e valori:
# Things become more complicated if there are duplicates in
# potential key values.This dict is arranged by hex, RGB, and HSL
# keys, but values repeat.
>>> extended_colors = {'#8076a3': 'Purple Mountains Majesty',
(128, 118, 163): 'Purple Mountains Majesty',
(21, 28, 0, 36): 'Purple Mountains Majesty',
'#f9c5bd': 'Misty Mountain Pink',
(249, 197, 189): 'Misty Mountain Pink',
(0, 21, 24, 2): 'Misty Mountain Pink',
'#7c677f': 'Factory Stone Purple',
(124, 103, 127): 'Factory Stone Purple',
(2, 19, 0, 50): 'Factory Stone Purple',
'#478559': 'Green Treeline',
(71, 133, 89): 'Green Treeline',
(47, 0, 33, 48): 'Green Treeline'}
# New empty dictionary for holding swapped entries.
>>> consolidated_colors = {}
# Iterating over (key, value) pairs using .items()
>>> for key, value in extended_color_reference.items():
... if value in consolidated_colors: # <--Check if key has already been created.
... consolidated_colors[value].append(key)
... else:
... consolidated_colors[value] = [key] # <--Create a value list with the former key in it.
>>> consolidated_colors
{'Purple Mountains Majesty': ['#8076a3', (128, 118, 163), (21, 28, 0, 36)],
'Misty Mountain Pink': ['#f9c5bd', (249, 197, 189), (0, 21, 24, 2)],
'Factory Stone Purple': ['#7c677f', (124, 103, 127), (2, 19, 0, 50)],
'Green Treeline': ['#478559', (71, 133, 89), (47, 0, 33, 48)]}
Per una spiegazione dettagliata dei dizionari e dei metodi per lavorarci, il tutorial ufficiale e il riferimento ufficiale della libreria sono ottimi punti di partenza.
Anche Real Python e Finxter hanno articoli molto approfonditi sui dizionari di Python.
Per saperne di più sull'ordinamento, vedi la guida Sorting HOW TO nella documentazione di Python.