Dizionari 2 - operatori
Scarica zip esercizi
Per manipolare i dizionari vi sono diversi operatori:
Operatore |
Sintassi |
Ritorna |
Descrizione |
---|---|---|---|
|
|
Ritorna il numero di chiavi |
|
dict |
obj |
Ritorna il valore associato alla chiave |
|
dict |
Aggiunge o modifica il valore associato ad una chiave |
||
|
Rimuove la coppia chiave/valore |
||
chiave |
|
Ritorna |
|
|
|
Controlla se due dizionari sono uguali o differenti |
Che fare
scompatta lo zip in una cartella, dovresti ottenere qualcosa del genere:
dictionaries
dictionaries1.ipynb
dictionaries1-sol.ipynb
dictionaries2.ipynb
dictionaries2-sol.ipynb
dictionaries3.ipynb
dictionaries3-sol.ipynb
dictionaries4.ipynb
dictionaries4-sol.ipynb
dictionaries5-chal.ipynb
jupman.py
ATTENZIONE: Per essere visualizzato correttamente, il file del notebook DEVE essere nella cartella szippata.
apri il Jupyter Notebook da quella cartella. Due cose dovrebbero aprirsi, prima una console e poi un browser. Il browser dovrebbe mostrare una lista di file: naviga la lista e apri il notebook
dictionaries2.ipynb
Prosegui leggendo il file degli esercizi, ogni tanto al suo interno troverai delle scritte ESERCIZIO, che ti chiederanno di scrivere dei comandi Python nelle celle successive.
Scorciatoie da tastiera:
Per eseguire il codice Python dentro una cella di Jupyter, premi
Control+Invio
Per eseguire il codice Python dentro una cella di Jupyter E selezionare la cella seguente, premi
Shift+Invio
Per eseguire il codice Python dentro una cella di Jupyter E creare una nuova cella subito dopo, premi
Alt+Invio
Se per caso il Notebook sembra inchiodato, prova a selezionare
Kernel -> Restart
len
E’ possibile ottenere il numero di associazioni chiave/valore presente in un dizionario usando la funzione len
:
[2]:
len({'a':5,
'b':9,
'c':7
})
[2]:
3
[3]:
len({3:8,
1:3
})
[3]:
2
[4]:
len({})
[4]:
0
DOMANDA: Guarda i seguenti frammenti di codice, e per ciascuno cerca di indovinare quale risultato produce (o se da errore):
len(dict())
len({'a':{}})
len({(1,2):{3},(4,5):{6},(7,8):{9}})
len({1:2,1:2,2:4,2:4,3:6,3:6})
len({1:2,',':3,',':4,})
len(len({3:4,5:6}))
Leggere un valore
In fondo alla definizione dei dizionari, è riportato
Data una chiave, possiamo reperire velocemente il valore corrispondente.
Come possiamo specificare la chiave di ricerca? Basta usare le quadre [
]
, un po’ come abbiamo già fatto per le liste:
[5]:
diz = { 'sedia' : 'un mobile per sedersi',
'armadio' : 'un mobile a ripiani',
'lampadario': 'un apparecchio di illuminazione'
}
[6]:
diz['sedia']
[6]:
'un mobile per sedersi'
[7]:
diz['lampadario']
[7]:
'un apparecchio di illuminazione'
ATTENZIONE Quello che mettiamo tra parentesi quadre deve essere una chiave presente nel dizionario
Se mettiamo chiavi non presenti, otterremo un errore:
>>> diz['tavolo']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-19-ee891f51417b> in <module>
----> 1 diz['tavolo']
KeyError: 'tavolo'
Disordine veloce
Quando diamo una chiave a Python, quanto è veloce a reperire il valore corrispondente? Tanto, così veloce che la velocità non dipende dalla dimensione del dizionario. Che sia piccolo o enorme, data una chiave troverà il valore associato in circa il medesimo tempo.
Quando abbiamo in mano un dizionario nella vita reale, tipicamente abbiamo una voce da cercare e lo sfogliamo finchè troviamo la voce ordinata: il fatto che le voci siano ordinate è quello che ci consente di trovare rapidamente la voce.
Potremmo aspettarci lo stesso anche in Python, invece guardando la definizione troviamo una notevole differenza:
I dizionari sono dei contenitori mutabili che ci consentono di associare velocemente voci dette chiavi a dei valori
Le chiavi sono immutabili, non hanno ordine e non vi possono essere duplicati
I valori possono essere duplicati
Se le chiavi non sono ordinate, come fa Python ad essere veloce a reperire i valori? La rapidità nasce dal fatto che Python memorizza le chiavi con un sistema con basato sugli hash simile al meccanismo impiegato per gli insiemi. Il prezzo da pagare per noi è l’imposizione di dover usare chiavi di tipo immutabile.
DOMANDA: Se volessimo stampare il valore 'un apparecchio di illuminazione'
che vediamo in fondo al dizionario, senza sapere che corrisponde a 'lampadario'
, avrebbe senso scrivere qualcosa del genere ?:
arredo = { 'sedia' : 'un mobile per sedersi',
'armadio' : 'un mobile a ripiani',
'lampadario': 'un apparecchio di illuminazione'
}
print( arredo[2] )
DOMANDA: Guarda le seguenti espressioni, e per ciascuna cerca di indovinare quale risultato producono (o se danno errore):
kabbalah = {
1 : 'Progresso',
3 : 'Amore',
5 : 'Creazione'
}
kabbalah[0]
kabbalah[1]
kabbalah[2]
kabbalah[3]
kabbalah[4]
kabbalah[5]
kabbalah[-1]
DOMANDA: Guarda le seguenti espressioni, e per ciascuna cerca di indovinare quale risultato producono (o se danno errore):
{'a':4,'b':5}('a')
{1:2,2:3,3:4}[2]
{'a':1,'b':2}['c']
{'a':1,'b':2}[a]
{'a':1,'b':2}[1]
{'a':1,'b':2,'c':3}['c']
{'a':1,'b':2,'c':3}[len(['a','b','c'])]
{(3,4):(1,2)}[(1,2)]
{(1,2):(3,4)}[(1,2)]
{[1,2]:[3,4]}[[1,2]]
{'a','b','c'}['a']
{'a:b','c:d'}['c']
{'a':4,'b':5}{'a'}
d1 = {'a':'b'} d2 = {'b':'c'} print(d1[d2['c']])
d1 = {'a':'b'} d2 = {'b':'c'} print(d2[d1['a']])
{}[]
{[]:3}[[]]
{1:7}['1']
{'':7}"[]"
{'':7}[""]
{"":7}['']
{'"':()}['']
{():7}[()]
{(()):7}[()]
{(()):7}[((),)]
Esercizio - z7
✪ Dato un dizionario diz1
con chiavi 'b'
e 'c'
associate a numeri, crea un dizionario diz2
che abbia una chiave 'z'
associata alla somma dei valori delle chiavi 'b'
e 'c'
di diz1
il tuo codice deve funzionare per qualunque
diz1
con chiavi'b'
e'c'
Esempio - dato:
diz1 = {'a':6, 'b':2,'c':5}
Dopo il tuo codice, deve risultare:
>>> print(diz2)
{'z': 7}
[8]:
diz1 = {'a':6, 'b':2,'c':5}
# scrivi qui
Scrivere nel dizionario
Possiamo scrivere in un dizionario?
I dizionari sono dei contenitori mutabili che ci consentono di associare velocemente voci dette chiavi a dei valori
La definizione parla di mutabilità, quindi una volta creati, possiamo successivamente modificarli.
I dizionari sono collezioni di coppie chiave/valore, e tra le modifiche possibili troviamo:
aggiunta di una coppia chiave/valore
associare una chiave esistente ad un valore diverso
rimuovere una coppia chiave/valore
Scrivere - aggiunta chiave/valore
Supponiamo di aver creato il nostro dizionario arredo
[9]:
arredo = { 'sedia' : 'un mobile per sedersi',
'armadio' : 'un mobile a ripiani',
'lampadario': 'un apparecchio di illuminazione'
}
e vogliamo in seguito aggiungere una definizione per 'divano'
. Possiamo riusare la variabile arredo
seguita da quadre con dentro la chiave che vogliamo aggiungere ['divano']
e dopo le quadre metteremo un segno di uguale =
[10]:
arredo['divano'] = 'mobile per rilassarsi'
Nota che Jupyter non ha mostrato risultati, perchè l’operazione precedente è un comando di assegnamento (solo le espressioni generano risultati).
Ma qualcosa comunque internamente nella memoria è successo, lo possiamo verificare stampando arredo
:
[11]:
arredo
[11]:
{'sedia': 'un mobile per sedersi',
'armadio': 'un mobile a ripiani',
'lampadario': 'un apparecchio di illuminazione',
'divano': 'mobile per rilassarsi'}
Notiamo che il dizionario associato alla variabile arredo
è stato MODIFICATO con l’aggiunta del divano.
Quando aggiungiamo una coppia chiave/valore, possiamo usare tipi eterogenei:
[12]:
bidone = {'bla':3,
4 : 'boh',
(7,9) : ['spaz','zatura']
}
[13]:
bidone[5.0] = 'un float'
[14]:
bidone
[14]:
{'bla': 3, 4: 'boh', (7, 9): ['spaz', 'zatura'], 5.0: 'un float'}
E siamo soggetti agli stessi vincoli sulle chiavi che abbiamo durante la creazione, quindi possiamo solo usare chiavi immutabili. Se proviamo ad immettere un tipo mutabile come per es. una lista, otteniamo un errore:
>>> bidone[ ['una', 'lista'] ] = 8
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-51-195ac9c21bcd> in <module>
----> 1 bidone[ ['una', 'lista'] ] = 8
TypeError: unhashable type: 'list'
DOMANDA: Guarda i seguenti frammenti di codice, e per ciascuno cerca di indovinare quale risultato produce (o se da errore):
diz = {1:'a'} diz[2] = 'a' print(diz)
diz = {} print(len(diz)) diz['a'] = 'b' print(len(diz))
diz1 = {'a':3, 'b':4} diz2 = diz1 diz1['a'] = 5 print(diz1) print(diz2)
diz1 = {'a':3, 'b':4} diz2 = dict(diz1) diz1['a'] = 5 print(diz1) print(diz2)
la = ['a','c'] diz = {'a':3, 'b':4, 'c':5} diz['d'] = diz[la[0]] + diz[la[1]] print(diz)
diz = {} diz[()]: '' diz[('a',)]: 'A' diz[('a','b')]: 'AB' print(diz)
la = [5,8,6,9] diz = {} diz[la[0]]=la[2] diz[la[2]]=la[0] print(diz)
diz = {} diz[(4,5,6)[2]] = 'c' diz[(4,5,6)[1]] = 'b' diz[(4,5,6)[0]] = 'a' print(diz)
diz1 = { 'a' : 'x', 'b' : 'x', 'c' : 'y', 'd' : 'y', } diz2 = {} diz2[diz1['a']] = 'a' diz2[diz1['b']] = 'b' diz2[diz1['c']] = 'c' diz2[diz1['d']] = 'd' print(diz2)
Scrivere - riassociare chiave
Supponiamo di voler cambiare la definizione di lampadario
:
[15]:
arredo = { 'sedia' : 'un mobile per sedersi',
'armadio' : 'un mobile a ripiani',
'lampadario': 'un apparecchio di illuminazione'
}
[16]:
arredo['lampadario'] = 'un apparecchio di illuminazione appeso al soffitto'
[17]:
arredo
[17]:
{'sedia': 'un mobile per sedersi',
'armadio': 'un mobile a ripiani',
'lampadario': 'un apparecchio di illuminazione appeso al soffitto'}
Esercizio - officina
✪ MODIFICA il dizionario officina
:
poni il valore della chiave
'bulloni'
uguale al valore della chiave'tenaglie'
incrementa il valore della chiave
ruote
di 1
il tuo codice deve funzionare per qualunque numero associato alle chiavi
NON creare nuovi dizionari, quindi niente linee che cominciano con
officina = {
Esempio - dati:
officina = {'ruote':3,
'bulloni':2,
'tenaglie':5}
dopo il tuo codice, devi ottenere:
>>> print(officina)
{'ruote': 4, 'bulloni': 5, 'tenaglie': 5}
[18]:
officina = {'ruote':3,
'bulloni':2,
'tenaglie':5}
# scrivi qui
DOMANDA: Guarda i seguenti frammenti di codice, e per ciascuno cerca di indovinare quale risultato produce (o se da errore):
diz = {'a':'b'} diz['a'] = 'a' print(diz)
diz = {'1':'2'} diz[1] = diz[1] + 5 # nasty print(diz)
diz = {1:2} diz[1] = diz[1] + 5 print(diz)
d1 = {1:2} d2 = {2:3} d1[1] = d2[d1[1]] print(d1)
Scrivere - cancellare
Per cancellare una coppia chiave/valore esiste il comando speciale del
. Prendiamo un dizionario:
[19]:
cucina = { 'pentole' : 3,
'padelle': 7,
'forchette' : 20
}
Se vogliamo eliminare la coppia 'padelle' : 7
, scriveremo del
seguito dal nome del dizionario e la chiave da eliminare tra quadre:
[20]:
del cucina['padelle']
[21]:
cucina
[21]:
{'pentole': 3, 'forchette': 20}
Cercare di cancellare una chiave inesistente produrrà un errore:
>>> del cucina['spinterogeno']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-34-c0d541348698> in <module>
----> 1 del cucina['spinterogeno']
KeyError: 'spinterogeno'
DOMANDA: Guarda i seguenti frammenti di codice, e per ciascuno cerca di indovinare quale risultato produce (o se da errore):
diz = {'a':'b'} del diz['b'] print(diz)
diz = {'a':'b', 'c':'d'} del diz['a'] print(diz)
diz = {'a':'b', 'c':'d'} del diz['a'] del diz['a'] print(diz)
diz = {'a':'b'} new_diz = del diz['a'] print(diz) print(new_diz)
diz1 = {'a':'b', 'c':'d'} diz2 = diz1 del diz1['a'] print(diz1) print(diz2)
diz1 = {'a':'b', 'c':'d'} diz2 = dict(diz1) del diz1['a'] print(diz1) print(diz2)
diz = {'a':'b'} del diz['c'] print(diz)
diz = {'a':'b'} diz.del('a') print(diz)
diz = {'a':'b'} diz['a'] = None print(diz)
Esercizio - scrivania
Dato un dizionario scrivania
:
scrivania = {
'carta':5,
'matite':2,
'penne':3
}
scrivi del codice che lo MODIFICA in modo che dopo l’esecuzione del tuo codice, il dizionario appaia così:
>>> print(scrivania)
{'carta': 4,'matite': 2, 'temperino': 1}
NON scrivere linee che iniziano con
scrivania =
(questo creerebbe un nuovo dizionario, invece noi vogliamo modificare quello esistente)
[22]:
scrivania = {
'carta':5,
'matite':2,
'penne':3
}
# scrivi qui
Esercizio - giardino
Hai un dizionario giardino
che associa nomi di oggetti presenti alla loro quantità. Ti vengono fornite:
una lista
da_togliere
contenente i nomi di esattamente 2 oggetti da eliminareun dizionario
da_aggiungere
contenente 2 nomi di fiori associati alla loro quantità da aggiungere
MODIFICA il dizionario giardino
secondo le quantità indicate da da_togliere
(cancellando le chiavi) e da_aggiungere
(incrementando i valori corrispondenti)
assumi che
giardino
contenga sempre gli oggetti indicati inda_togliere
eda_aggiungere
assumi che
da_aggiungere
contenga sempre e solotulipani
erose
Esempio:
da_togliere = ['erbacce', 'cartacce']
da_aggiungere = { 'tulipani': 4,
'rose' : 2
}
giardino = { 'ortensie': 3,
'tulipani': 7,
'erbacce' : 10,
'rose' : 5,
'cartacce': 6,
}
dopo il tuo codice, deve stampare
>>> print(giardino)
{'ortensie': 3, 'tulipani': 11, 'rose': 7}
[23]:
da_togliere = ['erbacce', 'cartacce']
da_aggiungere = {
'tulipani': 4,
'rose' : 2
}
giardino = { 'ortensie': 3,
'tulipani': 7,
'erbacce' : 10,
'rose' : 5,
'cartacce': 6,
}
# scrivi qui
Esercizio - traduzioni
Dati due dizionari en_it
e it_es
di traduzioni inglese-italiano e italiano-spagnolo, scrivi del codice che MODIFICA un terzo dizionario en_es
mettendoci traduzioni dall’inglese allo spagnolo
assumi che
en_it
contenga sempre e solo le traduzioni dihello
eroad
assumi che
it_es
contenga sempre e solo le traduzioni diciao
estrada
nella soluzione, usa SOLO le costanti
'hello'
e'road'
, le altre che ti servono dovrai recuperarle usando i dizionariNON creare un nuovo dizionario - quindi niente linee che iniziano con
en_es = {
Esempio - dati:
en_it = {
'hello' : 'ciao',
'road' : 'strada'
}
it_es = {
'ciao' : 'hola',
'strada' : 'carretera'
}
en_es = {}
dopo il tuo codice, dovrà stampare:
>>> print(en_es)
{'hello': 'hola', 'road': 'carretera'}
[24]:
en_it = {
'hello' : 'ciao',
'road' : 'strada'
}
it_es = {
'ciao' : 'hola',
'strada' : 'carretera'
}
en_es = {}
# scrivi qui
Appartenenza con in
Per verificare se una chiave è presente in un dizionario, possiamo usare l’operatore in
:
[25]:
'a' in {'a':5,'b':7}
[25]:
True
[26]:
'b' in {'a':5,'b':7}
[26]:
True
[27]:
'z' in {'a':5,'b':7}
[27]:
False
ATTENZIONE: in
cerca nelle chiavi , non nei valori !
[28]:
5 in {'a':5,'b':7}
[28]:
False
Come sempre quando operiamo con chiavi, non possiamo cercare un oggetto che sia mutabile, come per esempio le liste:
>>> [3,5] in {'a':'c','b':'d'}
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-41-3e3e336117aa> in <module>
----> 1 [3,5] in {'a':'c','b':'d'}
TypeError: unhashable type: 'list'
not in
E’ possibile verificare la non appartenza con l’operatore not in
:
[29]:
'z' not in {'a':5,'b':7}
[29]:
True
[30]:
'a' not in {'a':5,'b':7}
[30]:
False
Equivalentemente, possiamo usare quest’altra forma:
[31]:
not 'z' in {'a':5,'b':7}
[31]:
True
[32]:
not 'a' in {'a':5,'b':7}
[32]:
False
DOMANDA: Guarda i seguenti frammenti di codice, e per ciascuno cerca di indovinare quale risultato produce (o se da errore):
('a') in {'a':5}
('a','b') in {('a','b'):5}
('a','b',) in {('a','b'):5}
['a','b'] in {('a','b'):5}
{3: 'q' in {'q':5}}
{'q' not in {'q':0} : 'q' in {'q':0}}
{'a' in 'b'}
{'a' not in {'b':'a'}}
len({'a':6,'b':4}) in {1:2}
'ab' in {('a','b'): 'ab'}
None in {}
None in {'None':3}
None in {None:3}
not None in {0:None}
Esercizio - Il timoniere
Al ristorante “Il Timoniere” viene servito un menu
con esattamente 3 portate ciascuna abbinata ad un contorno. Le portate e i contorni sono numerati da 1 a 12. Vi sono molti clienti internazionali che non parlano bene l’italiano, quindi spesso indicano semplicemente un numero di portata. Non indicano mai un contorno.
Una volta ricevuta la richiesta
, il cameriere dispone di un tablet con cui verifica con ‘Cambusapp’ se il piatto è già pronto con il contorno corretto. Scrivi del codice che dato un indice di portata mostra True
se questa è in cambusa
abbinata alla portata, False
altrimenti.
NON usare
if
NON usare cicli o list comprehensions
SUGGERIMENTO: se non sai come fare, guarda Booleani - Ordine di valutazione
Esempio 1 - dati:
# 1 2 3 4 5 6
menu = ['aringa','burro','orata','insalata', 'salmone','patate',
# 7 8 9 10 11 12
'tonno', 'fagioli', 'salmone','limone', 'aringa', 'insalata']
cambusa = {'orata':'insalata',
'salmone':'patate',
'aringa':'insalata',
'tonno':'fagioli'}
richiesta = 1
Il programma mostrerà False
, perchè non c’è l’associazione "aringa" : "burro"
in cambusa
Esempio 2 - data:
richiesta = 3
il programma mostrerà True
perchè c’è l’associazione "orata" : "insalata"
in cambusa
[33]:
richiesta = 1 # False
#richiesta = 3 # True
#richiesta = 5 # True
#richiesta = 7 # True
#richiesta = 9 # False
#richiesta = 11 # True
# 1 2 3 4 5 6
menu = ['aringa','burro','orata','insalata', 'salmone','patate',
# 7 8 9 10 11 12
'tonno', 'fagioli', 'salmone','limone', 'aringa', 'insalata']
cambusa = {'orata':'insalata',
'salmone':'patate',
'aringa':'insalata',
'tonno':'fagioli'}
# scrivi qui
Dizionari di sequenze
Finora abbiamo quasi sempre associato alle chiavi un solo valore. E se volessimo associarne di più? Per esempio, supponiamo di essere una biblioteca e vogliamo associare agli utenti i libri che hanno preso in prestito. Potremmo rappresentare il tutto come un dizionario in cui al nome di ciascun utente si associa una lista con i libri presi in prestito:
[34]:
prestiti = {'Marco': ['I Miserabili', 'Ulisse'],
'Gloria': ['Guerra e pace'],
'Rita': ['Shining','Dracula','1984']}
Vediamo come è rappresentato in Python Tutor:
[35]:
# AFFINCHE' PYTHON TUTOR FUNZIONI, RICORDATI DI ESEGUIRE QUESTA CELLA con Shift+Invio
# (basta eseguirla una volta sola, la trovi anche all'inizio di ogni foglio)
import jupman
[36]:
prestiti = {'Marco': ['I Miserabili', 'Ulisse'],
'Gloria': ['Guerra e pace'],
'Rita': ['Shining','Dracula','1984']}
jupman.pytut()
[36]:
Se proviamo a scrivere l’espressione
[37]:
prestiti['Rita']
[37]:
['Shining', 'Dracula', '1984']
Python ci mostra la lista corrispondente. Quindi Python considera prestiti['Rita']
a tutti gli effetti come una lista, e come tale la possiamo usare. Per esempio, se volessimo accedere al libro unesimo della lista scriveremmo [1]
dopo l’espressione
[38]:
prestiti['Rita'][1]
[38]:
'Dracula'
Equivalentemente, potremmo anche salvarci un puntatore alla lista assegnando l’espressione ad una variabile:
[39]:
lista_rita = prestiti['Rita']
[40]:
lista_rita
[40]:
['Shining', 'Dracula', '1984']
[41]:
lista_rita[1]
[41]:
'Dracula'
Rivediamo il tutto in Python Tutor:
[42]:
prestiti = {'Marco': ['I Miserabili', 'Ulisse'],
'Gloria': ['Guerra e pace'],
'Rita': ['Shining','Dracula','1984']}
lista_rita = prestiti['Rita']
print(lista_rita[1])
jupman.pytut()
Dracula
[42]:
Se esegui il codice in Python Tutor, noterai come nel momento in cui assegnamo lista_rita
la lista corrispondente a Rita sembra ‘staccarsi’ dal dizionario. Questo è un solo effetto grafico causato da Python Tutor, dal punto di vista del dizionario non è cambiato nulla. L’intenzione è mostrare che la lista adesso è raggiungibile sia dal dizionario che dalla nuova variabile lista_rita
.
Esercizio - prestiti
Scrivi del codice per recuperare e stampare:
Il primo libro preso in prestito da Gloria (
'Guerra e Pace'
) e l’ultimo preso in prestito da Rita ('1984'
)Il numero di libri presi in prestito da Rita
True
se tutti tra Marco, Gloria e Rita hanno preso in prestito almeno un libro,False
altrimenti
[43]:
prestiti = {'Marco': ['I Miserabili', 'Ulisse'],
'Gloria': ['Guerra e pace'],
'Rita': ['Shining','Dracula','1984']}
# scrivi qui
1. Il primo libro preso in prestito da Gloria è Guerra e pace
L'ultimo libro preso in prestito da Rita è 1984
2. Rita ha preso in prestito 3 libro/i
3. Hanno preso tutti in prestito almeno un libro? True
Esercizio - La baia dello squalo
La West India Company ti ha richiesto di compiere una esplorazione nei mari tropicali noti per le specie pericolose che popolano le loro acque. Ti viene fornita una mappa
che associa dei luoghi alle specie ritrovate:
mappa = {
"Baia dello Squalo" : ["squali"],
"Estuario della Malasorte" : ["coccodrilli", "piraña"],
"Fossa del Naufragio" : ["orche assassine", "pesci tigre"],
}
Ti vengono altresì date delle indicazioni vaghe su come aggiornare la mappa
, usando queste variabili:
luogo = "Estuario della Malasorte"
pericoli = ["murene", "polpo blu maculato"]
viaggio = "Largo delle Vele Sommerse"
esplorazione = ['barracuda', 'meduse']
Prova a scrivere del codice che usando le variabili qua sopra (o dati dalla mappa stessa) MODIFICA mappa
al fine di ottenere:
>>> mappa
{'Baia dello Squalo' : ['squali'],
'Estuario della Malasorte' : ['coccodrilli', 'piraña', 'meduse'],
'Fossa del Naufragio' : ['orche assassine', 'pesci tigre'],
'Largo delle Meduse' : ['barracuda', 'meduse', 'coccodrilli', 'piraña']}
IMPORTANTE: NON usare stringhe costanti nel tuo codice (quindi es. niente
"Estuario della Malasorte"
…). Costanti numeriche sono invece ammesse.
[44]:
luogo = "Estuario della Malasorte"
pericoli = ["murene", "polpo blu maculato"]
viaggio = "Largo delle Vele Sommerse"
esplorazione = ['barracuda', 'meduse']
mappa = {
"Baia dello Squalo" : ["squali"],
"Estuario della Malasorte" : ["coccodrilli", "piraña"],
"Fossa del Naufragio" : ["orche assassine", "pesci tigre"],
}
# scrivi qui
Esercizio - Il mare della burrasca
La West India Company ti richiede di scrivere del codice per produrre una nuova
mappa a partire da mappa1
e mappa2
. La mappa nuova
deve contenere tutte le voci di mappa1
, espansa con le voci luogo1
e luogo2
da mappa2
.
assumi che le voci
luogo1
eluogo2
siano sempre presenti inmappa1
emappa2
IMPORTANTE: dopo l’esecuzione del tuo codice, sia
mappa1
chemappa2
devono risultare inalterate!
Esempio - date:
mappa1 = {
"Baia dello Squalo" : ["squali"],
"Estuario della Malasorte" : ["coccodrilli", "piraña"],
"Mare della Burrasca" : ["barracuda", "meduse"],
}
mappa2 = {
"Estuario della Malasorte" : ["murene", "pesci tigre"],
"Mare della Burrasca" : ["polipi giganti"],
"Fossa del Naufragio" : ["orche assassine"],
"Lago dei Disperati" : ["vortici d'acqua"],
}
luogo1, luogo2 = "Estuario della Malasorte", "Mare della Burrasca"
Dopo il tuo cordice, deve risultare:
>>> nuova
{'Baia dello Squalo': ['squali'],
'Estuario della Malasorte': ['coccodrilli', 'piraña', 'murene', 'pesci tigre'],
'Mare della Burrasca': ['barracuda', 'meduse', 'polipi giganti']}
>>> mappa1 # inalterata!
{'Baia dello Squalo': ['squali'],
'Estuario della Malasorte': ['coccodrilli', 'piraña'],
'Mare della Burrasca': ['barracuda', 'meduse']}
>>> mappa2 # inalterata!
{'Estuario della Malasorte': ['murene', 'pesci tigre'],
'Fossa del Naufragio': ['orche assassine'],
'Lago dei Disperati': ["vortici d'acqua"],
'Mare della Burrasca': ['polipi giganti']}
[45]:
mappa1 = {
"Baia dello Squalo" : ["squali"],
"Estuario della Malasorte" : ["coccodrilli", "piraña"],
"Mare della Burrasca" : ["barracuda", "meduse"],
}
mappa2 = {
"Estuario della Malasorte" : ["murene", "pesci tigre"],
"Mare della Burrasca" : ["polipi giganti"],
"Fossa del Naufragio" : ["orche assassine"],
"Lago dei Disperati" : ["vortici d'acqua"],
}
luogo1, luogo2 = "Estuario della Malasorte", "Mare della Burrasca"
# scrivi qui
Uguaglianza
Possiamo verificare se due dizionari sono uguali con l’operatore di uguaglianza ==
, che dati due dizionari ritorna True
se contengono coppie chiave/valore uguali oppure False
altrimenti:
[46]:
{'a':3, 'b':4} == {'a':3, 'b':4}
[46]:
True
[47]:
{'a':3, 'b':4} == {'c':3, 'b':4}
[47]:
False
[48]:
{'a':3, 'b':4} == {'a':3, 'b':999}
[48]:
False
Possiamo verificare l’uguaglianza di dizionari con numero di elementi diverso:
[49]:
{'a':3, 'b':4} == {'a':3}
[49]:
False
[50]:
{'a':3, 'b':4} == {'a':3,'b':3,'c':5}
[50]:
False
… e con elementi eterogenei:
[51]:
{'a':3, 'b':4} == {2:('q','p'), 'b':[99,77]}
[51]:
False
Uguaglianza e ordine
Dalla definizione:
Le chiavi sono immutabili, non hanno ordine e non vi possono essere duplicati
Visto che l’ordine non ha importanza, dizionari creati inserendo le stesse coppie chiavi/valore ma in ordine diverso saranno considerati uguali.
Esempio con creazione diretta:
[52]:
{'a':5, 'b':7} == {'b':7, 'a':5}
[52]:
True
Esempio con aggiunta graduale:
[53]:
diz1 = {}
diz1['a'] = 5
diz1['b'] = 7
diz2 = {}
diz2['b'] = 7
diz2['a'] = 5
print(diz1 == diz2)
True
DOMANDA: Guarda i seguenti frammenti di codice, e per ciascuno cerca di indovinare quale risultato produce (o se da errore):
{1:2} == {2:1}
{1:2,3:4} == {3:4,1:2}
{'a'.upper():3} == {'a':3}
{'A'.lower():3} == {'a':3}
{'a': {1:2} == {3:4}}
diz1 = {} diz1[2] = 5 diz1[3] = 7 diz2 = {} diz2[3] = 7 diz2[2] = 5 print(diz1 == diz2)
diz1 = {'a':3,'b':8} diz2 = diz1 diz1['a'] = 7 print(diz1 == diz2)
diz1 = {} diz1['a']=3 diz2 = diz1 diz2['a']=4 print(diz1 == diz2)
diz1 = {'a':3, 'b':4, 'c':5} diz2 = {'a':3,'c':5} del diz1['a'] print(diz1 == diz2)
diz1 = {} diz2 = {'a':3} diz1['a'] = 3 diz1['b'] = 5 diz2['b'] = 5 print(diz1 == diz2)
Uguaglianza e copie
Quando si duplicano contenitori che contengono oggetti mutabili, se non si presta attenzione si possono ottenere sorprese. Ritorniamo quindi sull’argomento copie di dizionari superficiale e in profondità, questa volta cercando di verificare l’effettiva uguaglianza con Python.
ATTENZIONE: Per comprendere quanto segue, è necessario (ri)guardare bene il foglio dizionari 1 - Copiare un dizionario
DOMANDA: Vediamo un esempio semplice, con una copia ‘manuale’. Se esegui il seguente codice in Python Tutor, cosa stamperà? Quante regioni di memoria vedrai?
diz1 = {'a':3,
'b':8}
diz2 = {'a':diz1['a'],
'b':diz1['b'] }
diz1['a'] = 6
print('uguali?', diz1 == diz2)
print('diz1=', diz1)
print('diz2=', diz2)
NOTA: tutti i valori (3
e 8
) sono immutabili.
[54]:
diz1 = {'a':3,
'b':8}
diz2 = {'a':diz1['a'],
'b':diz1['b'] }
diz1['a'] = 6
print('uguali?', diz1 == diz2)
print('diz1=', diz1)
print('diz2=', diz2)
jupman.pytut()
uguali? False
diz1= {'a': 6, 'b': 8}
diz2= {'a': 3, 'b': 8}
[54]:
DOMANDA: Se esegui il seguente codice in Python Tutor, cosa stamperà?
Che tipo di copia abbiamo fatto? Superficiale? In profondità? (o tutte e due..?)
Quante regioni di memoria vedrai?
diz1 = {'a':3,
'b':8}
diz2 = dict(diz1)
diz1['a'] = 7
print('uguali?', diz1 == diz2)
print('diz1=', diz1)
print('diz2=', diz2)
[55]:
diz1 = {'a':3,
'b':8}
diz2 = dict(diz1)
diz1['a'] = 7
print('uguali?', diz1 == diz2)
print('diz1=', diz1)
print('diz2=', diz2)
jupman.pytut()
uguali? False
diz1= {'a': 7, 'b': 8}
diz2= {'a': 3, 'b': 8}
[55]:
DOMANDA: Se esegui il seguente codice in Python Tutor, cosa stamperà?
Che tipo di copia abbiamo fatto? Superficiale? In profondità? (o tutte e due..?)
Quante regioni di memoria vedrai?
NOTA: i valori sono liste, perciò mutabili
diz1 = {'a':[1,2],
'b':[4,5,6]}
diz2 = dict(diz1)
diz1['a'].append(3)
print('uguali?', diz1 == diz2)
print('diz1=', diz1)
print('diz2=', diz2)
[56]:
diz1 = {'a':[1,2],
'b':[4,5,6]}
diz2 = dict(diz1)
diz1['a'].append(3)
print('uguali?', diz1 == diz2)
print('diz1=', diz1)
print('diz2=', diz2)
jupman.pytut()
uguali? True
diz1= {'a': [1, 2, 3], 'b': [4, 5, 6]}
diz2= {'a': [1, 2, 3], 'b': [4, 5, 6]}
[56]:
DOMANDA: Se esegui il seguente codice in Python Tutor, cosa stamperà?
Che tipo di copia abbiamo fatto? Superficiale? In profondità? (o tutte e due..?)
Quante regioni di memoria vedrai?
NOTA: i valori sono liste, perciò mutabili
import copy
diz1 = {'a':[1,2],
'b':[4,5,6]}
diz2 = copy.deepcopy(diz1)
diz1['a'].append(3)
print('uguali?', diz1 == diz2)
print('diz1=', diz1)
print('diz2=', diz2)
[57]:
import copy
diz1 = {'a':[1,2],
'b':[4,5,6]}
diz2 = copy.deepcopy(diz1)
diz1['a'].append(3)
print('uguali?', diz1 == diz2)
print('diz1=', diz1)
print('diz2=', diz2)
jupman.pytut()
uguali? False
diz1= {'a': [1, 2, 3], 'b': [4, 5, 6]}
diz2= {'a': [1, 2], 'b': [4, 5, 6]}
[57]:
DOMANDA: Guarda i seguenti frammenti di codice, e per ciascuno cerca di indovinare quale risultato produce (o se da errore):
diz1 = {'a':[4,5], 'b':[6,7]} diz2 = dict(diz1) diz2['a'] = diz1['b'] diz2['b'][0] = 9 print(diz1 == diz2) print(diz1) print(diz2)
da = {'a':['x','y','z']} db = dict(da) db['a'] = ['w','t'] dc = dict(db) print(da) print(db) print(dc)
import copy la = ['x','y','z'] diz1 = {'a':la, 'b':la } diz2 = copy.deepcopy(diz1) diz2['a'][0] = 'w' print('uguali?', diz1 == diz2) print('diz1=', diz1) print('diz2=', diz2)
Esercizio - Zoom Doom
Scrivi del codice che data una stringa s
(es 'ZOOM'
), crea un dizionario diz
ed assegna alle chiavi 'a'
, 'b'
e 'c'
la stessa identica lista contenente i caratteri della stringa come elementi (es ['Z','O','O','M']
).
in Python Tutor dovrai vedere 3 frecce che dalle chiavi puntano alla stessa identica regione di memoria
modificando la lista associata ad una chiave, dovresti vedere la modifica anche nei liste associate alle altre chiavi
il tuo codice deve funzionare per qualunque stringa
s
Esempio - data:
s = 'ZOOM'
Dopo il tuo codice, deve risultare:
>>> print(diz)
{'a': ['Z', 'O', 'O', 'M']
'b': ['Z', 'O', 'O', 'M'],
'c': ['Z', 'O', 'O', 'M'],
}
>>> diz['a'][0] = 'D'
>>> print(diz)
{'a': ['D', 'O', 'O', 'M']
'b': ['D', 'O', 'O', 'M'],
'c': ['D', 'O', 'O', 'M'],
}
[58]:
s = 'ZOOM'
# scrivi qui
Prosegui
Prosegui con Dizionari 3 - metodi