Sequenze e comprehensions
Scarica zip esercizi
In Python è possibile scrivere codice elegante e compatto con le sequenze. Prima vedremo come scorrere le sequenze con gli iteratori e poi come costruirle con le comprehensions di liste, insiemi e dizionari.
Che fare
scompatta lo zip in una cartella, dovresti ottenere qualcosa del genere:
sequences
sequences1.ipynb
sequences1-sol.ipynb
sequences2-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
sequences.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
Iterabili - liste
Guardando i cicli abbiamo spesso parlato di iteratazione su sequenze, ma nel dettaglio, cosa vuol dire esattamente che una sequenza è iterabile ? In concreto, vuol dire che è possibile chiamare la funzione iter
sulla sequenza.
Proviamo per esempio sulle familiari liste:
[2]:
iter(['a','b','c','d'])
[2]:
<list_iterator at 0x7faa8c0bd850>
Notiamo che Python ha creato un oggetto di tipo list_iterator
.
NOTA: la lista non viene mostrata!
Puoi immaginare un iteratore come una specie di macchinetta ferma, che ogni volta che viene azionata produce un elemento di una sequenza, uno alla volta.
Tipicamente, un iteratore sa solo in quale posizione sta all’interno di una sequenza, e può fornirci gli elementi della sequenza uno per uno se li chiediamo ripetutamente con la funzione next
:
[3]:
iteratore = iter(['a','b','c','d'])
[4]:
next(iteratore)
[4]:
'a'
[5]:
next(iteratore)
[5]:
'b'
[6]:
next(iteratore)
[6]:
'c'
[7]:
next(iteratore)
[7]:
'd'
Nota come l’iteratore abbia uno stato per tenere traccia di dove siamo nella sequenza (in inglese diremmo che è stateful). Lo stato viene cambiato ad ogni chiamata della funzione next
.
Se proviamo a chiedere più elementi di quanti ve ne sono disponibili, Python solleva un’eccezione StopIteration
:
next(iteratore)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-65-4518bd5da67f> in <module>()
----> 1 next(iteratore)
StopIteration:
iterabili - range
Abbiamo provato ad iterare su una lista, che è una sequenza completamente materializzata in memoria su cui scorriamo con l’oggetto iteratore. Esistono anche sequenze particolari che non sono materializzate in memoria, come per esempio range
.
Precedentemente abbiamo usato range
nei cicli for for ottenere una sequenza di numeri, ma esattamente, che cosa fa la funzione range
? Proviamo a chiamarla da sola:
[8]:
range(4)
[8]:
range(0, 4)
Forse ci attendevamo una sequenza di numeri, invece Python ci mostra un oggetto di tipo range
(indicando anche l’estremo inferiore del range).
NOTA: Al momento in memoria non è presente nessuna sequenza di numeri
Abbiamo solo un oggetto iterabile ‘fermo’ che se vogliamo può fornirci i numeri
Come possiamo chiederglieli?
Abbiamo già visto che si può usare un for
:
[9]:
for x in range(4):
print(x)
0
1
2
3
In alternativa, possiamo passare range
alla funzione iter
che produce un iteratore.
ATTENZIONE: range
è iterabile ma NON è un iteratore !!
Per ottenere l’iteratore dobbiamo chiamare la funzione iter
sull’oggetto range
[10]:
iteratore = iter(range(4))
Anche iter
produce un oggetto ‘fermo’, che non ha ancora materializzato in memoria dei numeri:
[11]:
iteratore
[11]:
<range_iterator at 0x7faa8f1f1ed0>
Per chiederglieli dobbiamo usare la funzione next
:
[12]:
next(iteratore)
[12]:
0
[13]:
next(iteratore)
[13]:
1
[14]:
next(iteratore)
[14]:
2
[15]:
next(iteratore)
[15]:
3
Nota come l’iteratore abbia uno stato, che viene cambiato ad ogni chiamata di next
per tenere traccia di dove siamo nella sequenza.
Se proviamo a chiedere più elementi di quanti ve ne sono disponibili, Python solleva un’eccezione StopIteration
:
next(iteratore)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-65-4518bd5da67f> in <module>()
----> 1 next(iteratore)
StopIteration:
Materializzare una sequenza
Abbiamo detto che un oggetto range
non materializza fisicamente in memoria tutti i numeri contemporaneamente. Solo ottenendo l’iteratore, li materializziamo uno per uno. E volessimo una lista con tutti i numeri ? Nel foglio sulle liste abbiamo visto che passando alla funzione list
una sequenza, viene creata una nuova lista che contiene tutti gli elementi della sequenza. Abbiamo parlato genericamente di
sequenza, ma il termine più corretto sarebbe stato iterabile.
Se passiamo a list
un qualunque oggetto iterabile allora verrà costruita la lista - come abbiamo visto range
è iterabile quindi proviamo:
[16]:
list(range(4))
[16]:
[0, 1, 2, 3]
Voilà ! Adesso la sequenza è tutta fisicamente presente in memoria.
ATTENZIONE: list
consuma l’iteratore!
Se provi a chiamare due volte list
sullo stesso iteratore, otterrai una lista vuota:
[17]:
sequenza = range(4)
iteratore = iter(sequenza)
[18]:
nuova1 = list(iteratore)
[19]:
nuova1
[19]:
[0, 1, 2, 3]
[20]:
nuova2 = list(iteratore)
[21]:
nuova2
[21]:
[]
E se volessimo accedere direttamente ad una posizione specifica della sequenza generata dall’iteratore? Proviamo ad estrarre direttamente la lettera ad indice 2 qui:
[22]:
sequenza = range(4)
iteratore = iter(sequenza)
iteratore[2]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-129-3c080cc9e700> in <module>()
1 sequenza = range(4)
2 iteratore = iter(sequenza)
----> 3 iteratore[3]
TypeError: 'range_iterator' object is not subscriptable
… purtroppo ci becchiamo un errore.
Non ci restano che due alternative:
prima convertiamo a lista e poi usiamo le quadre
chiamiamo 4 volte
next
(ricordati che gli indici partono da zero)
L’opzione a) spesso sembra comoda, ma fai attenzione: convertire a lista un’iteratore crea una NUOVA lista in memoria, se la lista di partenza è molto grande e/o si fa questa operazione molte volte si rischia di occupare memoria per niente.
Rivediamo l’esempio in Python Tutor:
[23]:
# 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
[24]:
sequenza = range(4)
iteratore = iter(sequenza)
nuova1 = list(iteratore)
nuova2 = list(iteratore)
jupman.pytut()
[24]:
DOMANDA: Occupa più memoria l’oggetto a
o l’oggetto b
?
a = range(10)
b = range(10000000)
DOMANDA: Occupa più memoria l’oggetto a
o l’oggetto b
?
a = list(range(10))
b = list(range(10000000))
Domande range
Guarda i seguenti frammenti di codice, e per ciascuno cerca di indovinare quale risultato produce (o se da errore):
range(3)
range()
list(range(-3))
range(3,6)
list(range(5,4))
list(range(3,3))
range(3) + range(6)
list(range(3)) + list(range(6))
list(range(0,6,2))
list(range(9,6,-1))
reversed
reversed
è una funzione che prende come parametro una sequenza e PRODUCE un NUOVO iteratore che consente di scorrere la sequenza in ordine inverso.
ATTENZIONE: chiamando reversed
si ottiene direttamente un iteratore !
Quindi non serve fare ulteriori chiamate a iter
come fatto per range
!
Vediamo meglio cosa vuol dire con un esempio:
[25]:
la = ['p','r','o','v','a']
[26]:
reversed(la)
[26]:
<list_reverseiterator at 0x7faa8c154fd0>
Vediamo che reversed
ha prodotto un risultato che è un iteratore (non una lista rovesciata).
INFO: gli iteratori occupano poca memoria
Creare un iteratore da una sequenza crea solo una specie di puntatore, non crea nuove regioni di memoria.
Inoltre, vediamo che la lista originale associata a la
non è cambiata:
[27]:
print(la)
['p', 'r', 'o', 'v', 'a']
ATTENZIONE: la funzione reversed
è diversa dal metodo reverse
Nota la d finale! Se provassiamo a chiamarla come un metodo otterremmo un errore:
>>> la.reversed()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-182-c8d1eec57fdd> in <module>
----> 1 la.reversed()
AttributeError: 'list' object has no attribute 'reversed'
iterare con next
Come facciamo ad ottenere in memoria una lista rovesciata? In altre parole, come facciamo ad azionare la macchinetta iteratore?
Possiamo chiedere all’iteratore un elemento alla volta con la funzione next
:
[28]:
la = ['a','b','c']
[29]:
iteratore = reversed(la)
[30]:
next(iteratore)
[30]:
'c'
[31]:
next(iteratore)
[31]:
'b'
[32]:
next(iteratore)
[32]:
'a'
Una volta esaurito l’iteratore, chiamando ancora next
otterremo un errore:
next(iteratore)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-248-4518bd5da67f> in <module>
----> 1 next(iteratore)
StopIteration:
Proviamo a crearci manualmente una lista di destinazione lb
e aggiungere gli elementi che otteniamo mano a mano:
[33]:
la = ['a','b','c']
iteratore = reversed(la)
lb = []
lb.append(next(iteratore))
lb.append(next(iteratore))
lb.append(next(iteratore))
print(lb)
jupman.pytut()
['c', 'b', 'a']
[33]:
Esercizio - sconcerto
Scrivi del codice che data una lista di caratteri la
, mette in una lista lb
tutti i caratteri in posizione dispari presi della lista la
rovesciata
usa
reversed
enext
NON modificare
la
NON usare indici negativi
NON usare
list
Esempio - data
# 8 7 6 5 4 3 2 1 0
la = ['s', 'c', 'o', 'n', 'c', 'e', 'r', 't', 'o']
lb = []
Dopo il tuo codice deve mostrare
>>> print(lb)
['t', 'e', 'n', 'c']
>>> print(la)
['s', 'c', 'o', 'n', 'c', 'e', 'r', 't', 'o']
Ti invitiamo a risolvere il problema in diversi modi:
MODO 1 - senza ciclo: Supponi che la lunghezza della lista sia fissa, e chiama ripetutamente next
senza usare un ciclo
MODO 2 - while: Supponi di avere una lista di lunghezza arbitraria, e prova a generalizzare il precedente codice usando un ciclo while
al cui interno chiamerai next
SUGGERIMENTO 1: tieni traccia della posizione a cui sei con un contatore
i
SUGGERIMENTO 2: non si può chiamare
len
su un iteratore, quindi nella condizione del while dovrai usare la lunghezza della lista originale
MODO 3 - for: questo è il modo più elegante. Supponi di avere una lista di lunghezza arbitraria e usa un ciclo for x in reversed(la)
SUGGERIMENTO: dovrai comunque tener traccia della posizione a cui sei con un contatore
i
[34]:
# MODO 1 MANUALE
# 8 7 6 5 4 3 2 1 0
la = ['s', 'c', 'o', 'n', 'c', 'e', 'r', 't', 'o']
lb = []
# scrivi qui
[35]:
# MODO 2 CON IL WHILE
# 8 7 6 5 4 3 2 1 0
la = ['s', 'c', 'o', 'n', 'c', 'e', 'r', 't', 'o']
lb = []
# scrivi qui
[36]:
# MODO 3: for
# 8 7 6 5 4 3 2 1 0
la = ['s', 'c', 'o', 'n', 'c', 'e', 'r', 't', 'o']
lb = []
# scrivi qui
Materializzare un iteratore
Per fortuna per ottenere subito una lista dall’iteratore c’è un modo meno laborioso.
Abbiamo visto che quando vogliamo creare una nuova lista a partire da una sequenza, possiamo usare list
come se fosse una funzione. Possiamo farlo anche in questo caso, interpretando l’iteratore come se fosse una sequenza:
[37]:
la = ['p', 'r', 'o', 'v', 'a']
list( reversed(la) )
[37]:
['a', 'v', 'o', 'r', 'p']
Nota bene abbiamo generato una NUOVA lista, quella originale associata ad la
è sempre la stessa:
[38]:
la
[38]:
['p', 'r', 'o', 'v', 'a']
Vediamo meglio cosa è successo usando Python Tutor (per evidenziare i passaggi abbiamo creato delle variabili extra):
[39]:
la = ['p','r','o','v','a']
iteratore = reversed(la)
nuova = list(iteratore)
print("la è",la)
print("nuova è",nuova)
jupman.pytut()
la è ['p', 'r', 'o', 'v', 'a']
nuova è ['a', 'v', 'o', 'r', 'p']
[39]:
DOMANDA Il seguente codice, che effetto produce?
la = ['p','o','n','t','e']
lb = list(reversed(reversed(la)))
sorted
La funzione sorted
prende una sequenza come parametro ritorna una NUOVA lista ordinata
ATTENZIONE: sorted
ritorna una LISTA, non un iteratore !
[40]:
sorted(['g','a','e','d','b'])
[40]:
['a', 'b', 'd', 'e', 'g']
ATTENZIONE: sorted
è una funzione diversa dal metodo sort !
Nota la ed finale! Se provassiamo a chiamarla come un metodo otterremmo un errore:
>>> la.sorted()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-182-c8d1eec57fdd> in <module>
----> 1 la.reversed()
AttributeError: 'list' object has no attribute 'sorted'
Esercizio - reversort
✪ Data una una lista di nomi, produrre una lista ordinata in ordine inverso
Ci sono almeno due modi per farlo in una sola linea di codice, trovarli entrambi
INPUT:
['Maria','Paolo','Giovanni','Alessia','Greta']
OUTPUT:
['Paolo', 'Maria', 'Greta', 'Giovanni', 'Alessia']
[41]:
# scrivi qui
zip
Supponiamo di avere due liste quadri
e anni
, con rispettivamente nomi di quadri famosi e le date in cui sono stati dipinti:
[42]:
quadri = ["La Gioconda", "La Nascita di Venere", "I Girasoli"]
anni = [1503, 1482, 1888]
Vogliamo produrre una lista nuova che contenga delle tuple che associano a ciascun quadro l’anno in cui è stato dipinto:
[('La Gioconda', 1503),
('La Nascita di Venere', 1482),
('I Girasoli', 1888)]
Per farlo vi sono vari modi ma senz’altro il più elegante è con la funzione zip
che produce un iteratore:
[43]:
zip(quadri, anni)
[43]:
<zip at 0x7faa76734780>
Per quanto non si veda scritto ‘iteratore’ nel nome dell’oggetto, possiamo comunque usarlo come tale con next
:
[44]:
iteratore = zip(quadri, anni)
next(iteratore)
[44]:
('La Gioconda', 1503)
[45]:
next(iteratore)
[45]:
('La Nascita di Venere', 1482)
[46]:
next(iteratore)
[46]:
('I Girasoli', 1888)
E come fatto in precedenza, possiamo convertire tutto a lista con list
:
[47]:
quadri = ["La Gioconda", "La Nascita di Venere", "I Girasoli"]
anni = [1503, 1482, 1888]
list(zip(quadri,anni))
[47]:
[('La Gioconda', 1503), ('La Nascita di Venere', 1482), ('I Girasoli', 1888)]
Se le liste sono di lunghezza differente, la sequenza prodotta da zip
sarà lunga come la sequenza di input più corta:
[48]:
list(zip([1,2,3], ['a','b','c','d','e']))
[48]:
[(1, 'a'), (2, 'b'), (3, 'c')]
Volendo, si può passare un numero arbitrario di sequenze - per esempio passandone tre otteremo delle triple di valori:
[49]:
canzoni = ['Imagine', 'Hey Jude', 'Satisfaction', 'Yesterday' ]
autori = ['John Lennon','The Beatles', 'The Rolling Stones', 'The Beatles']
anni = [1971, 1968, 1965, 1965]
list(zip(canzoni, autori, anni))
[49]:
[('Imagine', 'John Lennon', 1971),
('Hey Jude', 'The Beatles', 1968),
('Satisfaction', 'The Rolling Stones', 1965),
('Yesterday', 'The Beatles', 1965)]
Esercizio - scala
Data una numero n
, creare una lista di tuple che per ogni numero intero \(x\) tale che \(0 \leq x \leq n\) associa il numero \(n - x\)
INPUT:
n=5
OUTPUT:
[(0, 4), (1, 3), (2, 2), (3, 1), (4, 0)]
[50]:
n = 5
# scrivi qui
List comprehensions
Le list comprehensions servono per generare una NUOVA lista eseguendo la stessa operazione su tutti gli elementi di una sequenza di partenza. Come sintassi imitano le liste, infatti iniziano e finiscono con le parentesi quadre [
]
, ma dentro contengono un for
speciale per ciclare dentro un sequenza :
[51]:
numeri = [2,5,3,4]
raddoppiati = [x*2 for x in numeri]
raddoppiati
[51]:
[4, 10, 6, 8]
Nota che la variabile numeri
è ancora associata alla lista originale:
[52]:
numeri
[52]:
[2, 5, 3, 4]
Cosa è successo ? Abbiamo indicato a Python un nome di variabile x
che ci siamo inventati noi, e gli abbiamo detto di scorrere la lista numeri
: ad ogni iterazione, la variabile x
viene associata ad un diverso valore della lista numeri
. Tale valore lo possiamo riusare nell’espressione che indichiamo a sinistra del for
, che in questo caso è x*2
.
Come nome per la variabile abbiamo usato x
, ma potremmo usare un qualunque altro nome, per esempio questo codice è equivalente al precedente:
[53]:
numeri = [2,5,3,4]
raddoppiati = [numero * 2 for numero in numeri]
raddoppiati
[53]:
[4, 10, 6, 8]
Nella parte a sinistra del for
possiamo scrivere qualunque espressione che produca un valore, per esempio qua scriviamo x + 1
per incrementare tutti i numeri della lista originale.
[54]:
numeri = [2,5,3,4]
aumentati = [x + 1 for x in numeri]
aumentati
[54]:
[3, 6, 4, 5]
DOMANDA: Questo codice cosa produrrà? Se lo visualizziamo in Python Tutor, la
ed lb
punteranno ad oggetti diversi?
la = [7,5,6,9]
lb = [x for x in la]
[55]:
la = [7,5,6,9]
lb = [x for x in la]
jupman.pytut()
[55]:
list comprehension su stringhe
DOMANDA: Questo codice cosa produrrà?
[x for x in 'domanda']
Adesso supponiamo di avere una lista di animali
e vogliamo produrne un’altra con gli stessi nomi ma in maiuscolo. Possiamo farlo in modo compatto con una list comprehension così:
[56]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
nuova_lista = [animale.upper() for animale in animali]
[57]:
nuova_lista
[57]:
['CANI', 'GATTI', 'SCOIATTOLI', 'ALCI']
Nella parte a sinistra riservata all’espressione abbiamo usato sulla variabile stringa animale
il metodo .upper()
. Sappiamo che le stringhe sono immutabili, quindi siamo sicuri che la chiamata al metodo produce una NUOVA stringa. Vediamo cosa è successo in Python Tutor:
[58]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
nuova_lista = [animale.upper() for animale in animali]
jupman.pytut()
[58]:
✪ ESERCIZIO: Prova qua sotto ad usare una list comprehension per mettere tutti i caratteri in minuscolo (metodo .lower()
)
[59]:
animali = ['caNI', 'gaTTi', 'SCOIATtoli', 'aLLci']
# scrivi qui
Domande list comprehension
Guarda i seguenti frammenti di codice, e per ciascuno cerca di indovinare quale risultato produce (o se da errore):
[x for [4,2,5]]
x for x in range(3)
[x for y in 'cartoccio']
[for x in 'zappa']
[for [3,4,5]]
[k + 1 for k in 'bozza']
[k + 1 for k in range(5)]
[k > 3 for k in range(7)]
[s + s for s in ['lam','pa','da']]
la = ['x','z','z'] [x for x in la] + [y for y in la]
[x.split('-') for x in ['a-b', 'c-d', 'e-f']]
['@'.join(x) for x in [['a','b.com'],['c','d.org'],['e','f.net'] ]]
['z' for y in 'borgo'].count('z') == len('borgo')
m = [['a','b'],['c','d'],['e','f'] ] la = [x.pop() for x in m] # sconsigliabile - perchè ? print(' m:', m) print('la:',la)
Esercizio - list comprehension
Esercizio - Bubble bubble
✪ Data una lista di stringhe, produrre una sequenza con tutte le stringhe replicate 4 volte
INPUT:
['gomma', 'ciunga', 'cicca']
OUTPUT:
['gommagommagommagomma', 'ciungaciungaciungaciunga', 'ciccaciccaciccacicca']
[60]:
bubble_bubble = ['gomma', 'ciunga', 'cicca']
# scrivi qui
Esercizio - radice
✪ Data una lista di numeri, produrre una lista con la radice quadrata dei numeri di input
INPUT:
[16,25,81]
OUTPUT:
[4.0, 5.0, 9.0]
[61]:
import math
# scrivi qui
[61]:
[4.0, 5.0, 9.0]
Esercizio - QuandoFuoriPiove
✪ Data una lista di stringhe, produrre una lista con i primi caratteri di ogni stringa
INPUT:
['Quando', 'Fuori', 'Piove', 'Programmiamo']
OUTPUT:
['Q','F','P','P']
[62]:
# scrivi qui
[62]:
['Q', 'F', 'P', 'P']
Esercizio - porta pazienza
✪ Da una lista di stringhe, produrre una lista con le lunghezze di tutte le liste
INPUT:
['non', 'ti', 'preoccupare', 'e', 'porta', 'pazienza']
OUTPUT:
[3,2,11,1,5,8]
[63]:
# scrivi qui
Esercizio - maggiore 3
✪ Data una lista di numeri, produrre una lista con True
se il corrispondente elemento è maggiore di 3
, False
altrimenti
INPUT:
[4,1,0,5,0,9,1]
OUTPUT:
[True, False, False, True, False, True, False]
[64]:
# scrivi qui
Esercizio - pari
✪ Data una lista di numeri, produrre una lista con True
se il corrispondente elemento è pari
INPUT:
[3,2,4,1,5,3,2,9]
OUTPUT:
[False, True, True, False, False, False, True, False]
[65]:
# scrivi qui
Esercizio - capi
✪ Data una lista di stringhe di almeno due caratteri, produrre una lista di stringhe con i primi e ultimi caratteri
INPUT:
['parto', 'per', 'il', 'fronte']
OUTPUT:
['po', 'pr', 'il', 'fe']
[66]:
# scrivi qui
Esercizio - trattini
✪ Data una lista di liste di caratteri, produrre una lista di stringhe con caratteri separati da trattini
INPUT:
[['a','b'],['c','d','e'], ['f','g']]
OUTPUT:
['a-b', 'c-d-e', 'f-g']
[67]:
# scrivi qui
Esercizio - lollosa
✪ Data una stringa s
, produrre una lista di tuple avente per ogni carattere il numero di occorrenze del carattere nella stringa.
INPUT:
s = 'lollosa'
OUTPUT:
[('l', 3), ('o', 2), ('l', 3), ('l', 3), ('o', 2), ('s', 1), ('a', 1)]
[68]:
s = 'lollosa'
# scrivi qui
Esercizio - cane gatto
✪ Data una lista di stringhe, produrre una lista con le stringhe senza caratteri iniziale e finale
INPUT:
['bue','gatto','cane', 'mucca' ]
OUTPUT:
['u', 'att', 'an', 'ucc']
[69]:
# scrivi qui
Esercizio - puffi
✪ Dati dei nomi produrre una lista ordinata con i nomi in ordine alfabetico tutti in maiuscolo
INPUT:
['Quattrocchi', 'Forzuto', 'Puffetta', 'Tontolone']
OUTPUT:
['FORZUTO', 'PUFFETTA', 'QUATTROCCHI', 'TONTOLONE']
[70]:
# scrivi qui
Esercizio - metalli preziosi
✪ Date due liste valori
e metalli
produrre una lista contenente tutte le coppie valore metallo come tuple
INPUT:
valori = [10,25,50]
metalli = ['argento','oro','platino']
OUTPUT: [(10, 'argento'), (25, 'oro'), (50, 'platino')]
[71]:
valori = [10,25,50]
metalli = ['argento','oro','platino']
# scrivi qui
List comprehension filtrate
Durante la costruzione di una list comprehension è possibile filtrare gli elementi presi dalla sequenza che si sta esaminando utilizzando un if
. Per esempio, l’espressione seguente considera dalla sequenza di numeri solo i numeri maggiori di cinque:
[72]:
[x for x in [7,4,8,2,9] if x > 5]
[72]:
[7, 8, 9]
Dopo l’if
possiamo mettere qualunque espressione che riusi la variabile su cui stiamo iterando, per esempio se stiamo iterando su una stringa possiamo trattenere solo i caratteri maiuscoli:
[73]:
[x for x in 'Il Mondo Gira' if x.isupper()]
[73]:
['I', 'M', 'G']
ATTENZIONE: gli else
non sono supportati
Per esempio, scrivere questo genera un errore:
[x for x in [7,4,8,2,9] if x > 5 else x + 1] # SBAGLIATO!
File "<ipython-input-74-9ba5c135c58c>", line 1
[x for x in [7,4,8,2,9] if x > 5 else x + 1]
^
SyntaxError: invalid syntax
Domande list comprehension filtrate
Guarda i seguenti frammenti di codice, e per ciascuno cerca di indovinare quale risultato produce (o se da errore):
[x for x in range(100) if False]
[x for x in range(3) if True]
[x for x in range(6) if x > 3 else 55]
[x for x in range(6) if x % 2 == 0]
[x for x in {'a','b','c'}] # occhio all'ordine
[x for x in [[5], [2,3], [4,2,3], [4]] if len(x) > 2]
[(x,x) for x in 'xyxyxxy' if x != 'x' ]
[x for x in ['abCdEFg'] if x.upper() == x]
la = [1,2,3,4,5] [x for x in la if x > la[len(la)//2]]
Esercizi - list comprehension filtrate
Esercizio - savana
Data una lista di stringhe, produrre una lista con solo le stringhe di lunghezza maggiore di 6
INPUT:
['zebra', 'leopardo', 'giraffa', 'gnu', 'rinoceronte', 'leone']
OUTPUT:
['leopardo', 'giraffa', 'rinoceronte']
[74]:
# scrivi qui
Esercizio - barZa
Data una lista di stringhe, produrre una lista con solo le stringhe che contengono almeno una 'z'
. Le stringhe selezionate vanno trasformate in modo da mettere la Z
in maiuscolo.
INPUT:
['barza', 'palco','porzione', 'corsa', 'maschera', 'zona']
OUTPUT:
['barZa', 'porZione', 'Zona']
[75]:
# scrivi qui
Esercizio - Data science
Produrre una stringa con le parole della stringa in ingresso alternate maiuscolo / minuscolo
INPUT:
[76]:
frase = """La data science è l'insieme di principi metodologici
basati sul metodo scientifico e di tecniche multidisciplinari
volto a interpretare ed estrarre conoscenza dai dati attraverso
la relativa fase di analisi"""
OUTPUT (su una sola linea):
LA data SCIENCE è L'INSIEME di PRINCIPI metodologici BASATI sul METODO scientifico E di TECNICHE multidisciplinari VOLTO a INTERPRETARE ed ESTRARRE conoscenza DAI dati ATTRAVERSO la RELATIVA fase DI analisi
✪✪✪ SCRIVI UNA SOLA linea di codice
✪✪✪✪ USA con UNA SOLA comprehension
Mostra soluzione[77]:
frase = """La data science è l'insieme di principi metodologici
basati sul metodo scientifico e di tecniche multidisciplinari
volto a interpretare ed estrarre conoscenza dai dati attraverso
la relativa fase di analisi"""
# scrivi qui
Prosegui
Continua con le challenges