Introduzione rapida a Python
Scarica zip esercizi
REQUISITI:
QUESTO FOGLIO E’ PER CHI HA GIA’ COMPETENZE DI PROGRAMMAZIONE, e in 3-4h vuole farsi rapidamente un’idea di Python
Aver installati Python 3 e Jupyter: se non hai già provveduto, guarda Installazione
SE SEI UN PRINCIPIANTE: Salta questo foglio e fai invece i tutorial che trovi nella sezione Fondamenti, a partire da Strumenti e script
Che fare
scompatta lo zip in una cartella, dovresti ottenere qualcosa del genere:
Per essere visualizzato correttamente, il file del notebook DEVE essere nella cartella szippata.
quick-intro
quick-intro.ipynb
quick-intro-sol.ipynb
jupman.py
ATTENZIONE: In questo libro usiamo SOLO PYTHON 3
Se per caso ottieni comportamenti inattesi, controlla di usare Python 3 e non il 2. Se per caso il tuo sistema operativo scrivendo python
fa partire il 2, prova ad eseguire il tre scrivendo il comando: python3
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
quick-intro.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. Gli esercizi sono graduati per difficoltà, da una stellina ✪ a quattro ✪✪✪✪
Ricordati di eseguire sempre la prima cella dentro il notebook.
Contiene delle istruzioni come import jupman
che dicono a Python quali moduli servono e dove trovarli. Per eseguirla, vedi le seguenti scorciatoie
Scorciatoie da tastiera per utenti Windows e Linux:
Per eseguire il codice Python dentro una cella di Jupyter, premi
Ctrl+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
Se sei un utente Mac, sostituisci i tasti sopra con i seguenti:
Ctrl -> Command
⌘
Shift -> Shift
⇧
Alt -> Option
⌥
Proviamo Jupyter
Vediamo brevemente come funzionano i fogli Jupyter.
ESERCIZIO: Proviamo a inserire un comando Python: scrivi nella cella qua sotto l’espressione 3 + 5
, e poi mentre sei in quella cella premi i tasti speciali Control+Invio
. Un’espressione produce sempre un risultato, in questo caso dovresti vedere apparire il numero 8
[ ]:
ESERCIZIO: in Python possiamo scrivere commenti iniziando una riga con un cancelletto #
. Come prima, scrivi nella cella sotto 3 + 5
ma questa volta scrivilo nella riga sotto la scritta # scrivi qui
:
[2]:
# scrivi qui
ESERCIZIO: Jupyter per ogni cella mostra il risultato solo dell’ultima riga eseguita in quella cella. Prova a inserire questo codice nella cella sotto ed esegui premendo Control+Invio
. Che risultato appare?
3 + 5
1 + 1
[3]:
# scrivi qui
ESERCIZIO: Proviamo adesso a creare noi una nuova cella.
Mentre sei con il cursore in questa cella, premi
Alt+Invio
. Si dovrebbe creare una nuova cella dopo la presente.Nella cella appena creata, inserisci
2 + 3
e poi premiShift+Invio
. Cosa succede al cursore? Prova la differenze conControl+Invio
. Se non capisci la differenza, prova a premere ripetutamenteShift+Invio
e vedi che succede.
Principali tipi di dati Python
Dato che il tema del libro è il trattamento dei dati, per cominciare ci focalizzeremo sui tipi di dati in Python.
Riferimenti:
Quando leggiamo delle informazioni da una fonte esterna come un file, poi dovremo inevitabilmente incastonare i dati letti in qualche combinazione di questi tipi:
Tipo |
Esempio 1 |
Esempio 2 |
Esempio 3 |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
``[“qualcosa”, 5, “altro ancora”]` ` |
|
|
|
|
A volte, useremo tipi più complessi, per esempio i valori temporali si potrebbero mettere in oggetti di tipo datetime
che oltre alla data vera e propria possono contenere anche il fuso orario.
In quel che segue, forniremo alcuni esempi rapidi su quello che si può fare sui vari tipi di dato, mettendo riferimenti a spiegazioni più dettagliate nel resto del libro.
Numeri interi e con virgola
Mettiamo qua due note velocissime:
Riferimenti:
In Python abbiamo numeri interi:
[4]:
3 + 5
[4]:
8
La somma tra interi ovviamente ci da un intero:
[5]:
type(8)
[5]:
int
E se dividiamo interi? Ci troveremo con il tipo in virgola mobile float:
[6]:
3 / 4
[6]:
0.75
[7]:
type(0.75)
[7]:
float
ATTENZIONE al punto !
In Python e in molti formati dati, al posto della nostra virgola si usa il formato inglese con il punto ‘.’
✪ ESERCIZIO: Prova a scrivere qua sotto 3.14
con il punto, e poi 3,14
con la virgola ed esegui con Ctrl+Invio. Cosa appare nei due casi?
[8]:
# scrivi qui con il punto
[9]:
# scrivi qui con la virgola
✪ ESERCIZIO: Prova a scrivere qua sotto 3 + 1.0
ed esegui con Ctrl+Invio. Di quale tipo sarà il risultato? Controlla anche usando il comando type
.
[10]:
# scrivi qui i comandi
✪ ESERCIZIO: Qualche professore di matematica ti avrà sicuramente intimato di non dividere mai per zero. Neanche a Python piace molto, prova a scrivere nella cella qua sotto 1 / 0
e poi premi Ctrl+Invio per eseguire la cella. Nota come Python riporterà la riga dove è accaduto l’errore:
[11]:
# scrivi qui sotto il codice
Booleani - bool
I booleani rappresentano valori veri e falsi, e si possono usare per verificare quando certe condizioni avvengono.
Riferimenti
Per indicare i booleani Python ci fornisce due costanti True
e False
. Cosa ci possiamo fare?
Operatore and
Potremmo usarle per segnare in variabili se un certo fatto è avvenuto, per esempio possiamo fare un programma che al mattino ci dice che possiamo uscire di casa solo dopo aver fatto entrambe (and
) colazione e lavato i denti:
[12]:
fatto_colazione = True
lavato_denti = True
if fatto_colazione and lavato_denti:
print("fatto tutto !")
print("posso uscire di casa")
else:
print("NON posso uscire di casa")
fatto tutto !
posso uscire di casa
✪ ESERCIZIO: prova a scrivere qui sotto a mano il programma riportato nella cella precedente, ed eseguilo con Control+Invio. Prova a cambiare i valori da True
a False
e guarda che succede.
Assicurati di provare tutti i casi:
True True
True False
False True
False False
ATTENZIONE: Ricordati i :
alla fine della riga con if
!!!!
[13]:
# scrivi qui
Si può anche mettere un if
dentro l’altro (nested if). Per esempio, questo programma qui funziona esattamente come il precedente:
[14]:
fatto_colazione = True
lavato_denti = True
if fatto_colazione:
if lavato_denti: # NOTA: Questo blocco if è indentato rispetto
print("fatto tutto !") # all' if fatto_colazione
print("posso uscire di casa!") #
else:
print("NON posso uscire di casa")
else:
print("NON posso uscire di casa")
fatto tutto !
posso uscire di casa!
✪ ESERCIZIO: Prova a modificare il programma riportato nella cella precedente per fargli riportare lo stato delle varie azioni compiute. Elenchiamo qui i possibili casi e i risultati attesi:
True False
ho fatto colazione
non ho lavato i denti
NON posso uscire di casa
False True
False False
non ho fatto colazione
NON posso uscire di casa
True True
ho fatto colazione ho lavato i denti fatto tutto ! posso uscire di casa!
[15]:
# scrivi qui
Operatore or
Per verificare se almeno di due condizioni si è verificata, si usa or
. Per esempio, possiamo stabilire che per fare colazione ci serve avere del latte intero o scremato (nota: se li abbiamo tutte e due riusciamo a fare colazione lo stesso !)
[16]:
ho_latte_intero = True
ho_latte_scremato = False
if ho_latte_intero or ho_latte_scremato:
print("posso fare colazione !")
else:
print("NON posso fare colazione :-(")
posso fare colazione !
✪ ESERCIZIO: prova a scrivere qui sotto a mano il programma riportato nella cella presedente, ed eseguilo con Control+Invio. Prova a cambiare i valori da True
a False
e guarda che succede:
Assicurati di provare tutti i casi:
True True
True False
False True
False False
[17]:
# scrivi qui
✪✪ ESERCIZIO: prova a fare un programma che ti dice se puoi uscire di casa solo se hai fatto colazione (per cui devi avere hai almeno un tipo di latte) e lavato i denti
Mostra soluzione[18]:
ho_latte_intero = False
ho_latte_scremato = True
lavato_denti = False
# scrivi qui
posso fare colazione !
NON posso uscire di casa
Operatore not
Per le negazioni, puoi usare il not
:
[19]:
not True
[19]:
False
[20]:
not False
[20]:
True
[21]:
fatto_colazione = False
if not fatto_colazione:
print("Ho fame !")
else:
print("che buoni che erano i cereali")
Ho fame !
[22]:
fatto_colazione = True
if not fatto_colazione:
print("Ho fame !")
else:
print("che buoni che erano i cereali")
che buoni che erano i cereali
✪✪ ESERCIZIO: prova a fare un programma che ti dice se puoi nuotare se NON hai fatto colazione E hai il salvagente
Assicurati di provare tutti i casi:
True True
True False
False True
False False
[23]:
hai_salvagente = True
fatto_colazione = True
# scrivi qui
NON puoi nuotare
Non solo True e False
ATTENZIONE ai booleani diversi da True e False !
In Python, il numero 0
e altri oggetti ‘nulli’ (come l’oggetto None
, la stringa vuota ""
e la lista vuota []
) sono considerati False
, e tutto ciò che non è ‘nullo’ è considerato True
!
Facciamo degli esempi per mostrare quanto sopra riportato:
[24]:
if True:
print("questo")
print("sarà")
print("stampato")
else:
print("quest'altro")
print("non sarà stampato")
questo
sarà
stampato
Tutto ciò che non è ‘nullo’ è considerato True
, verifichiamolo per esempio con la stringa "ciao"
:
[25]:
if "ciao":
print("anche questo")
print("sarà stampato!!")
else:
print("e questo no")
anche questo
sarà stampato!!
[26]:
if False:
print("io non sarò stampato")
else:
print("io sì")
io sì
[27]:
if 0:
print("anche questo non sarà stampato")
else:
print("io sì")
io sì
[28]:
if None:
print("neppure questo sarà stampato")
else:
print("io sì")
io sì
[29]:
if "": # stringa vuota
print("Neanche questo sarà stampato !!!")
else:
print("io sì")
io sì
✪ ESERCIZIO: Copia qua sotto l’if
una stringa con uno spazio dentro " "
nella condizione dell’if
. Cosa succederà?
prova anche a mettere una lista vuota
[]
, che succede?
[30]:
# scrivi qui l'if
Stringhe - str
Le stringhe sono sequenze immutabili di caratteri.
Riferimenti:
SoftPython:
Concatenare stringhe
Una delle cose che si fanno più frequentemente è concatenare delle stringhe:
[31]:
"ciao " + "mondo"
[31]:
'ciao mondo'
Ma nota che quando concateniamo una stringa e un numero, Python si arrabbia:
"ciao " + 5
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-38-e219e8205f7d> in <module>()
----> 1 "ciao " + 5
TypeError: Can't convert 'int' object to str implicitly
Questo succede perchè Python vuole che convertiamo esplicitamente il numero ‘5’ in una stringa. Porrà simili lamentela anche con altri tipi di oggetti. Quindi, quando concatenate oggetti che non sono stringhe, per evitare problemi racchiudete l’oggetto da convertire nella funzione str
come qui:
[32]:
"ciao " + str(7)
[32]:
'ciao 7'
Un modo alternativo e più veloce è usare l’operatore di formattazione percentuale %
, che sostituisce alle occorrenze di %s
quello che mettete dopo un %
dopo la stringa :
[33]:
"ciao %s" % 7
[33]:
'ciao 7'
Meglio ancora, il %s
può stare all’interno della stringa e venire ripetuto. Per ogni occorrenza si può passare un sostituto diverso, come per esempio nella tupla ("bello", "Python")
(una tupla è semplicemente una sequenza immutabile di elementi racchiusi tra parentesi tonde e separati da virgole)
[34]:
"Che %s finalmente imparo %s" % ("bello", "Python")
[34]:
'Che bello finalmente imparo Python'
✪ ESERCIZIO: il %s
funziona con le stringhe ma anche con quasiasi altro tipo di dato, per esempio un intero. Scrivi qua sotto il comando sopra, aggiunendo un %s
alla fine della stringa, e aggiungendo alla fine della tupla il numero 3
(separandolo dagli altri con una virgola).
Domanda: i %s
possono stare uno dopo l’altro senza spazi tra di loro? Prova.
[35]:
# scrivi qui
Usare metodi degli oggetti
Quasi tutto in Python è un oggetto, faremo qui una velocissima introduzione tanto per dare l’idea.
Riferimenti
Quasi tutto in Python è un oggetto. Per esempio, le stringhe sono oggetti. Ogni tipo di oggetto ha delle azioni chiamati metodi che si possono eseguire su quello oggetto. Per esempio, per le stringhe che rappresentano nomi potremmo voler rendere in maiuscolo la prima lettera: a tal fine possiamo cercare se per le stringhe ci sono giò metodi esistenti che fanno questo. Proviamo il metodo esistente capitalize()
sulla stringa "trento"
(notare che la stringa è tutta in minuscolo e
capital in inglese vuol anche dire ‘maiuscolo’ ):
[36]:
"trento".capitalize()
[36]:
'Trento'
Python ci ha appena fatto la cortesia di rendere la prima lettera della parola in maiuscolo 'Trento'
✪ ESERCIZIO: Scrivi nella cella qua sotto "trento".
e premi TAB: Jupyter dovrebbe suggerirti dei metodi disponibili per la stringa. Prova il metodo upper()
e count("t")
[37]:
# scrivi qui
Liste - list
Una lista in python è una sequenza mutabile di elementi eterogenei, in cui possiamo mettere gli oggetti che vogliamo.
Riferimenti - SoftPython:
Creiamo una lista di stringhe:
[38]:
x = ["ciao", "soft", "python"]
[39]:
x
[39]:
['ciao', 'soft', 'python']
Le liste sono sequenze di oggetti possibilmente eterogenei, quindi dentro ci potete buttare di tutto, interi, stringhe, dizionari …:
[40]:
x = ["ciao", 123, {"a":"b"}]
[41]:
x
[41]:
['ciao', 123, {'a': 'b'}]
Per accedere ad un elemento in particolare dentro una lista, si può usare un indice tra parentesi quadre che indica un elemento:
[42]:
# primo elemento
x[0]
[42]:
'ciao'
[43]:
# secondo elemento
x[1]
[43]:
123
[44]:
# terzo elemento
x[2]
[44]:
{'a': 'b'}
In una lista possiamo cambiare gli elementi con l’assegnazione:
[45]:
# Cambiamo il *secondo* elemento:
x[1] = "soft"
[46]:
x
[46]:
['ciao', 'soft', {'a': 'b'}]
[47]:
x[2] = "python"
[48]:
x
[48]:
['ciao', 'soft', 'python']
Per ottenere la lunghezza di una lista, possiamo usare len
:
[49]:
x = ["ciao", "soft", "python"]
len(x)
[49]:
3
✪ ESERCIZIO: prova ad accedere ad un elemento fuori dalla lista, e vedi che succede.
x[3]
è dentro o fuori dalla lista?C’è una qualche lista
x
per cui possiamo scriverex[len(x)]
senza problemi ?se usi indici negativi, che succede? Prova -1, -2, -3, -4 …
[50]:
# scrivi qui
Possiamo aggiungere elementi alla fine di una lista usando il comando append
:
[51]:
x = []
[52]:
x
[52]:
[]
[53]:
x.append("ciao")
[54]:
x
[54]:
['ciao']
[55]:
x.append("soft")
[56]:
x
[56]:
['ciao', 'soft']
[57]:
x.append("python")
[58]:
x
[58]:
['ciao', 'soft', 'python']
Ordinamento liste
Le liste possono ordinare comodamente con il metodo .sort
, che funziona su tutti gli oggetti ordinabili. Per esempio, possiamo ordinare i numeri:
IMPORTANTE: .sort()
modifica la lista su cui è chiamato, non ne genera una nuova !
[59]:
x = [ 8, 2, 4]
x.sort()
[60]:
x
[60]:
[2, 4, 8]
Come altro esempio, possiamo ordinare le stringhe:
[61]:
x = [ 'mondo', 'python', 'ciao',]
x.sort()
x
[61]:
['ciao', 'mondo', 'python']
Se non volessimo modificare la lista originale e invece volessimo generarne una nuova, useremmo la funzione sorted()
. NOTA: sorted
è una funzione, non un metodo:
[62]:
x = [ 'mondo', 'python', 'ciao',]
sorted(x)
[62]:
['ciao', 'mondo', 'python']
[63]:
# l'x originale non è cambiato:
x
[63]:
['mondo', 'python', 'ciao']
✪ ESERCIZIO: Che succede se ordini stringhe contenenti gli stessi caratteri ma maiscoli invece di minuscoli? Come vengono ordinati? Fai delle prove.
[64]:
# scrivi qui
✪ ESERCIZIO: Che succede se nella stessa lista metti sia stringhe che numeri e provi ad ordinarla? Fai delle prove.
[65]:
# scrivi qui
Ordine rovesciato
Supponiamo di voler ordinare la lista alla rovescia usando sorted
. Per fare cioò possiamo indicare a Python il parametro booleano reverse
e il suo valore, che in questo caso sarà True
. Questo ci permette di notare come Python consenta di usare parametri opzionali specificandoli per nome :
[66]:
sorted(['mondo', 'python', 'ciao'], reverse=True)
[66]:
['python', 'mondo', 'ciao']
✪ ESERCIZIO: Per cercare informazioni su sorted
, avremmo potuto chiedere a Python dell’aiuto. Per fare ciò Python mette a disposizione una comoda funzione chiamata help
, che potresti usare così help(sorted)
. Prova ad eseguirla nella cella qua sotto. A volte l’help è piuttosto complesso, e sta a noi sforzarci un po’ per individuare i parametri di interesse
[67]:
# scrivi qui
Rovesciare liste non ordinate
E se volessimo rovesciare una lista così com’è, senza ordinarla in senso decrescente, per esempio per passare da[6,2,4]
a [2,4,6]
Cercando un po’ nella libreria di Python, vediamo che c’è una comoda funzione reversed()
che prende come paramatro la lista che vogliamo rovesciare e ne genera una nuova rovesciata.
✪ ESERCIZIO: Prova ad eseguire reversed([6,2,4])
nella cella qua sotto, e guarda che output ottieni. E’ quello che ti aspetti ? In genere, e specialmente in Python 3, quando ci aspettiamo una lista e per caso vediamo invece un oggetto col nome iterator
, possiamo risolvere passando il risultato come parametro della funzione list()
[68]:
# scrivi qui il codice
Dizionari - dict
I dizionari sono dei contenitori che ci consentono di abbinare dei valori a delle voci dette chiavi. Qua faremo un esempio rapidissimo per dare un’idea.
Riferimenti:
SoftPython - dizionari:
Possiamo creare un dizionario con le graffe {
}
, separando le chiavi dai valori con i due punti :
, e separando le coppie chiave/valore con la virgola ,
:
[69]:
d = { 'chiave 1':'valore 1',
'chiave 2':'valore 2' }
Per accedere ai valori, possiamo usare le chiavi tra parentesi quadre:
[70]:
d['chiave 1']
[70]:
'valore 1'
[71]:
d['chiave 2']
[71]:
'valore 2'
Valori: come valori nei dizionari possiamo mettere quello che ci pare, numeri, stringhe, tuple, liste, altri dizionari ..
[72]:
d['chiave 3'] = 123
[73]:
d
[73]:
{'chiave 1': 'valore 1', 'chiave 2': 'valore 2', 'chiave 3': 123}
[74]:
d['chiave 4'] = ('io','sono', 'una', 'tupla')
[75]:
d
[75]:
{'chiave 1': 'valore 1',
'chiave 2': 'valore 2',
'chiave 3': 123,
'chiave 4': ('io', 'sono', 'una', 'tupla')}
✪ ESERCIZIO: prova ad inserire nel dizionario delle coppie chiave valore con chiavi stringa e come valori delle liste e altri dizionari,
[76]:
# scrivi qui:
Chiavi: Per le chiavi abbiamo delle restrizioni: possono essere solo tipi immutabili. Abbiamo già usato le stringhe quindi sappiamo che sono immutabili. Anche i numeri sono immutabili:
[77]:
d[123] = 'valore 3'
[78]:
d
[78]:
{'chiave 1': 'valore 1',
'chiave 2': 'valore 2',
'chiave 3': 123,
'chiave 4': ('io', 'sono', 'una', 'tupla'),
123: 'valore 3'}
Le tuple sono sequenze immutabili perciò possiamo usarle come chiavi:
[79]:
d[('io','sono','una','tupla')] = 'valore 4'
[80]:
d
[80]:
{'chiave 1': 'valore 1',
'chiave 2': 'valore 2',
'chiave 3': 123,
'chiave 4': ('io', 'sono', 'una', 'tupla'),
123: 'valore 3',
('io', 'sono', 'una', 'tupla'): 'valore 4'}
ATTENZIONE: Non tutti i tipi vanno bene a Python come chiavi. Senza andare nei dettagli, in genere non puoi inserire nei dizionari dei tipi che possono essere modificati dopo che sono stati creati.
✪ ESERCIZIO:
Prova ad inserire in un dizionario una lista tipo
['a','b']
come chiave, e come valore metti quello che vuoi. Python non dovrebbe permetterti di farlo, e ti dovrebbe mostrare la scrittaTypeError: unhashable type: 'list'
prova anche ad inserire un dizionario come chiave (per es. anche il dizionario vuoto
{}
). Che risultato ottieni?
Visualizzare l’esecuzione con Python Tutor
Abbiamo visto i principali tipi di dati. Prima di procedere oltre, è bene vedere gli strumenti giusti per comprendere al meglio cosa succede quando si esegue il codice. Python tutor è un ottimo sito online per visualizzare online l’esecuzione di codice Python, permettendo di andare avanti e indietro nell’esecuzione del codice. Sfruttatelo più che potete, dovrebbe funzionare con parecchi degli esempi che tratteremo nel libro. Vediamo un esempio.
Python tutor 1/4
Vai sul sito pythontutor.com e seleziona Python 3
Python tutor 2/4
Python tutor 3/4
Python tutor 4/4
Debuggare codice in Jupyter
Python tutor è fantastico, ma quando esegui del codice in Jupyter e non funziona, come si può fare? Per ispezionare l’esecuzione, gli editor di solito mettono a disposizione uno strumento chiamato debugger, che permette di eseguire le istruzioni una per una. Al momento (Agosto 2018), il debugger di Jupyter che si chiama pdb è estremamente limitato . Per superarne le limitazioni, in questo libro ci siamo inventati una soluzione di ripiego, che sfrutta Python Tutor.
Se inserisci del codice Python in una cella, e poi alla fine della cella scrivi l’istruzione jupman.pytut()
, come per magia il codice precedente verrà visualizzato all’interno del foglio Jupyter con il debugger di Python Tutor.
ATTENZIONE: jupman
è una collezione di funzioni di supporto che ci siamo inventati apposta per questo libro.
Quando vedi comandi che iniziano con jupman
, affinchè funzionino devi prima eseguire la cella in cima al documento. Riportiamo tale cella qua per comodità. Se non lo hai già fatto, eseguila adesso.
[81]:
# Ricordati di eseguire questa cella con Control+Invio
# Questi comandi dicono a Python dove trovare il file jupman.py
import jupman;
Adesso siamo pronti a provare Python tutor con la funzione magica jupman.pytut()
:
[82]:
x = 5
y = 7
z = x + y
jupman.pytut()
[82]:
Python Tutor : Limitazione 1
Python tutor è comodo, ma ci sono importanti limitazioni:
ATTENZIONE: Python Tutor guarda dentro una cella sola!
Quando usi Python tutor dentro Jupyter, l’unico codice che viene considerato da Python tutor è quello dentro la cella dove sta il comando jupman.pytut()
.
Quindi per esempio in queste due celle che seguono, solo print(w)
apparirà dentro Python tutor senza il w = 3
. Se proverai a cliccare Forward in Python tutor, ti verrà segnalato che non è stata definita w
[83]:
w = 3
[84]:
print(w)
jupman.pytut()
3
Traceback (most recent call last):
File "../jupman.py", line 2453, in _runscript
self.run(script_str, user_globals, user_globals)
File "/usr/lib/python3.7/bdb.py", line 578, in run
exec(cmd, globals, locals)
File "<string>", line 2, in <module>
NameError: name 'w' is not defined
[84]:
Per avere tutto in Python tutor devi mettere tutto il codice nella stessa cella:
[85]:
w = 3
print(w)
jupman.pytut()
3
[85]:
Python Tutor : Limitazione 2
Un’altra limitazione è la seguente:
ATTENZIONE: Python tutor usa solo funzioni dalla distribuzione standard di Python**
Python Tutor va bene per ispezionare semplici algoritmi che usano funzioni di base di Python.
Se usate qualche libreria tipo numpy
, potete provare solo online a selezionare Python 3.6 with anaconda
Iterazione
Spesso è utile compiere azioni su ogni elemento di una sequenza.
Riferimenti
Cicli for
Tra i vari modi per farlo, uno è usare i cicli for
[86]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
for animale in animali:
print("Nella lista ci sono:")
print(animale)
Nella lista ci sono:
cani
Nella lista ci sono:
gatti
Nella lista ci sono:
scoiattoli
Nella lista ci sono:
alci
Qua abbiamo definito la variabile animale
(avremmo potuto chiamarla con qualunque nome, anche pippo
). Per ogni elemento nella lista animali
, vengono eseguite le istruzioni dentro il blocco. Ogni volta che le istruzioni vengono eseguite, la variabile animale
assume uno dei valori della lista animali
ATTENZIONE 1: RICORDATI I DUE PUNTI :
ALLA FINE DELLA LINEA DEL FOR !!!
ATTENZIONE 2: Per indentare il codice, usa SEMPRE sequenze di 4 spazi bianchi.
Sequenze di 2 soli spazi per quanto consentite non sono raccomandate.
ATTENZIONE 3: Il comportamento di TAB dipende dal tuo editor.
A seconda dell’editor che usi, premendo TAB potresti ottenere una sequenza di spazi bianchi come accade in Jupyter (4 spazi che sono raccomandati), oppure un carattere speciale di tabulazione (da evitare)! Per quanto noiosa questa distinzione ti possa apparire, ricordatela perchè potrebbe generare errori molto difficili da scoprire.
[87]:
# Guardiamo cosa succede con Python tutor:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
for animale in animali:
print("Nella lista ci sono:")
print(animale)
jupman.pytut()
Nella lista ci sono:
cani
Nella lista ci sono:
gatti
Nella lista ci sono:
scoiattoli
Nella lista ci sono:
alci
[87]:
✪ ESERCIZIO: Proviamo a capire meglio tutti gli Attenzione qua sopra. Scrivi qui sotto il for
con gli animali di prima (niente copia e incolla!), vedi se funziona. Ricordati di usare 4 spazi per le indentazioni.
Poi prova a togliere i due punti alla fine e vedi che errore ti da Python
Riaggiungi i due punti, e adesso prova a variare l’indentazione. Prova a mettere due spazi all’inizio di entrambi i print, vedi se esegue
Adesso prova a mettere due spazi prima del primo print e 4 spazi prima del secondo, e vedi se esegue
[88]:
# scrivi qui - copia il for di sopra
for in range
Un’altra iterazione molto comune è incrementare un contatore ad ogni ciclo. Python rispetto ad altri linguaggi offre un sistema piuttosto particolare che usa la funzione range(n)
, che ritorna una sequenza con i primi numeri da 0
incluso a n
escluso. La possiamo usare così:
[89]:
for indice in range(3):
print(indice)
0
1
2
[90]:
for indice in range(6):
print(indice)
0
1
2
3
4
5
Guardiamo meglio con Python tutor:
[91]:
for indice in range(6):
print(indice)
jupman.pytut()
0
1
2
3
4
5
[91]:
Quindi possiamo usare questo stile come un’alternativa per listare i nostri animali:
[92]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
for indice in range(3):
print("Nella lista ci sono:")
print(animali[indice])
Nella lista ci sono:
cani
Nella lista ci sono:
gatti
Nella lista ci sono:
scoiattoli
Guardiamo meglio con Python tutor:
[93]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
for indice in range(3):
print("Nella lista ci sono:")
print(animali[indice])
jupman.pytut()
Nella lista ci sono:
cani
Nella lista ci sono:
gatti
Nella lista ci sono:
scoiattoli
[93]:
Funzioni
Una funzione prende dei parametri e li usa per produrre o riportare qualche risultato.
Riferimenti
Per definire una funzione, possiamo usare la parola chiave def
:
[94]:
def mia_stampa(x,y): # RICORDATI I DUE PUNTI ':' ALLA FINE DELLA RIGA !!!!!
print('Ora stamperemo la somma di due numeri')
print('La somma è %s' % (x + y))
Possiamo chiamare la funzione così:
[95]:
mia_stampa(3,5)
Ora stamperemo la somma di due numeri
La somma è 8
Vediamo meglio che succede con Python Tutor:
[96]:
def mia_stampa(x,y): # RICORDATI I DUE PUNTI ':' ALLA FINE DELLA RIGA !!!!!
print('Ora stamperemo la somma di due numeri')
print('La somma è %s' % (x + y))
mia_stampa(3,5)
jupman.pytut()
Ora stamperemo la somma di due numeri
La somma è 8
[96]:
La funzione appena dichiarata stampa dei valori, ma non ritorna nulla. Per fare una funzione che ritorni un valore, dobbiamo usare la parola chiava return
Trovi questo tipo di funzioni anche sul libro Pensare in Python, Capitolo 6, Funzioni produttive, di cui puoi fare tutto saltando la parte 6.5 sulla ricorsione. NOTA: nel libro viene usato il termine strano “funzioni produttive” per quelle funzioni che ritornano un valore, ed il termine ancora più strano “funzioni vuote” per funzioni che non ritornano nulla ma fanno qualche effetto tipo stampa a video: ignora questi strani termini !
[97]:
def mia_somma(x,y):
s = x + y
return s
[98]:
mia_somma(3,5)
[98]:
8
[99]:
# Vediamo meglio che succede con Python Tutor:
def mia_somma(x,y):
s = x + y
return s
print(mia_somma(3,5))
jupman.pytut()
8
[99]:
✪ ESERCIZIO: Se proviamo ad assegnare ad una variabile x
il valore di ritorno delle funzione mia_stampa
che apparentemente non ritorna nulla, che valore ci sarà in x
? Prova a capirlo qua sotto:
[100]:
# scrivi qui
✪ ESERCIZIO: Scrivi qua sotto una funzione media
che calcola e ritorna la media tra due numeri x e y in input
[101]:
# scrivi qui
✪✪ ESERCIZIO: Scrivi qua sotto una funzione che chiameremo iniziab
che prende una stringa x
in ingresso. Se la stringa inizia con la lettera 'b'
, per esempio 'bianco'
la funzione stampa la scritta bianco inizia con b
, altrimenti stampa che non inizia con la b.
Per controllare se il primo carattere è uguale alla
'b'
, usa l’operatore==
(ATTENZIONE: è un DOPPIO uguale !)Se la stringa è vuota la tua funzione può avere problemi? Come potresti risolverli? (Per separare più condizioni nell’
if
, usa l’operatoreand
oppureor
a seconda di come hai costruito l’if).
[102]:
# scrivi qui
bianco inizia con b
verde non inizia con b
non inizia con b
Funzioni lambda
In Python una variabile può contenere una funzione. Per esempio, sappiamo che len("ciao")
ci dà la lunghezza della stringa "ciao"
[103]:
len("ciao")
[103]:
4
Proviamo a creare una variabile mia_variabile
che punta alla funzione len
.
[104]:
mia_variabile = len
NOTA: non abbiamo aggiunto parametri a len
!
Adesso possiamo usare mia_variabile
esattamente come usiamo la funzione len
, che da la lunghezza di sequenze come le stringhe
[105]:
mia_variabile("ciao")
[105]:
4
Possiamo anche riassegnare mia_variabile
ad altre funzioni, per esempio sorted
. Vediamo che succede:
[106]:
mia_variabile = sorted
chiamando mia_variabile
, ci aspettiamo di vedere i caratteri di "ciao"
in ordine alfabetico:
[107]:
mia_variabile("ciao")
[107]:
['a', 'c', 'i', 'o']
In Python possiamo definire funzioni in una sola riga, con le cosiddette funzioni lambda:
[108]:
mia_f = lambda x: x + 1
Cosa fa mia_f
? Prende un parametro x
e ritorna il risultato di calcolare l’espressione x + 1
:
[109]:
mia_f(5)
[109]:
6
Possiamo anche passare due parametri:
[110]:
mia_somma = lambda x,y: x + y
[111]:
mia_somma(3,5)
[111]:
8
✪ ESERCIZIO: Prova a definire qua sotto una funzione lambda per calcolare la media tra due numeri x
e y
, e assegnala alla variabile media
[112]:
# scrivi qui
Trasformazioni sulle liste
Riferimenti:
Supponiamo di voler prendere la lista di animali e generarne una nuova in cui tutti i nomi iniziano con la lettera maiuscola. Questa che vogliamo fare di fatto è la creazione di una nuova lista operando una trasformazione sulla precedente. Per fare ciò esistono diversi modi, quello più semplice è usare un ciclo for
così
Trasfomazioni con il for
[113]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
nuova_lista = []
for animale in animali: # ad ogni ciclo la variabile 'animale' contiene un nome preso dalla lista 'animali'
nuova_lista.append(animale.capitalize()) # aggiungiamo alla nuova lista il nome dell'animale corrente, con la prima lettera maiuscola
nuova_lista
#vediamo che succede con Python tutor
jupman.pytut()
[113]:
Nota importante: i metodi sulle stringhe non modificano mai la stringa originale, ma ne generano sempre una nuova. Quindi la lista originale animali
conterrà ancora le stringhe originale senza modifiche:
[114]:
animali
[114]:
['cani', 'gatti', 'scoiattoli', 'alci']
✪ ESERCIZIO: Prova a scrivere qua sotto un ciclo for
(senza usare il copia e incolla!) che scorre la lista dei nomi degli animali e crea un’altra lista che chiameremo m
in cui tutti i caratteri dei nomi degli animali sono in maiuscolo (usa il metodo .upper()
)
[115]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
# scrivi qui
Trasformazioni con le list comprehension
Riferimenti: SoftPython - Sequenze
La stessa identica trasformazione di sopra si potrebbe attuare con una cosiddetta list comprehension, che servono per generare nuove liste eseguendo la stessa operazione su tutti gli elementi di una lista esistente 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 :
[116]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
nuova_lista = [animale.capitalize() for animale in animali]
[117]:
nuova_lista
[117]:
['Cani', 'Gatti', 'Scoiattoli', 'Alci']
Vediamo che succede con Python tutor:
[118]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
nuova_lista = [animale.capitalize() for animale in animali]
jupman.pytut()
[118]:
✪ ESERCIZIO: Prova qua sotto ad usare una list comprehension per mettere tutti i caratteri in maiuscolo
Mostra soluzione[119]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
# scrivi qui
Filtrare con le comprehension: Volendo, possiamo anche filtrare i dati usando un if
speciale da mettere alla fine della comprehension. Per esempio potremmo selezionare solo gli animali la cui lunghezza del nome è di 4 caratteri:
[120]:
[animale.upper() for animale in animali if len(animale) == 4]
[120]:
['CANI', 'ALCI']
Trasformazioni con le map
Un’altro modo ancora per trasformare una lista in una nuova è usare l’operazione map
, che a partire da una lista, ne genera un’altra applicando ad ogni elemento della lista di partenza una funzione f
che passiamo come parametro. Per risolvere lo stesso esercizio precedente, si potrebbe per esempio creare al volo con lambda
una funzione f
che mette la prima lettera di una stringa in maiuscolo, e poi si potrebbe chiamare la map
passando la f
appena creata:
[121]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
f = lambda animale: animale.capitalize()
map(f, animali)
[121]:
<map at 0x7f3ba80e2150>
Purtroppo il risultato non è esattamente la lista che volevamo. Il problema è che Python 3 aspetta a ritornarci una lista vera e propria, e invece ci ritorna un iteratore. Come mai? Python 3 per ragioni di efficienza spera che non non andremo mai ad usare nessun elemento della nuova lista, evitandogli di fatto la fatica di applicare la funzione a tutti gli elementi della lista originale. Ma noi possiamo forzarlo a darci la lista che vogliamo usando la funzione list
:
[122]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
f = lambda animale: animale.capitalize()
list(map(f, animali))
[122]:
['Cani', 'Gatti', 'Scoiattoli', 'Alci']
Per avere un esempio totalmente equivalente ai precedenti, possiamo assegnare il risultato a nuova_lista
:
[123]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
f = lambda animale: animale.capitalize()
nuova_lista = list(map(f, animali))
[124]:
nuova_lista
[124]:
['Cani', 'Gatti', 'Scoiattoli', 'Alci']
Un vero hacker Python probabilmente preferirà scrivere tutto in una sola linea, così:
[125]:
animali = ['cani', 'gatti', 'scoiattoli', 'alci']
nuova_lista = list(map(lambda animale: animale.capitalize(), animali))
[126]:
nuova_lista
[126]:
['Cani', 'Gatti', 'Scoiattoli', 'Alci']
✪ ESERCIZIO: la lista originale animali
è cambiata? Controlla.
✪ ESERCIZIO: Data una lista numeri = [3, 5, 2, 7]
prova a scrivere una map
che genera una nuova lista con i numeri raddoppiati, come [6, 10, 4, 14]
:
[127]:
numeri = [3, 5, 2, 7]
# scrivi qui
Matrici
Finita la presentazione, è ora di sforzarsi un po’ di più. Vediamo brevemente matrici come liste di liste. Per approfondire, guardare i riferimenti.
Riferimenti:
✪✪ ESERCIZIO: Date le due liste con nomi di animali e corrispondente aspettativa di vita in anni:
animali = ['cane', 'gatto', 'pellicano', 'scoiattolo', 'aquila']
anni = [12,14,30,6,25]
Scrivere nella cella sotto del codice che generi una lista di liste da due elementi, così:
[ ['cane', 12], ['gatto', 14], ['pellicano', 30], ['scoiattolo', 6], ['aquila', 25] ]
[128]:
animali = ['cane', 'gatto', 'pellicano', 'scoiattolo', 'aquila']
anni = [12,14,30,6,25]
# scrivi qui
✪✪ ESERCIZIO modificare scrivendolo qua sotto il codice dell’esercizio precedente nella versione con il normale ciclo for
per filtrare solo le specie con aspettativa di vita superiore ai 13 anni, così da ottenere questo risultato:
[['gatto', 14], ['pellicano', 30], ['aquila', 25]]
[129]:
animali = ['cane', 'gatto', 'pellicano', 'scoiattolo', 'aquila']
anni = [12,14,30,6,25]
# scrivi qui
ESERCIZIO Scrivi qua sotto del codice con un normale ciclo for
per filtrare solo le specie con aspettativa di vita superiore ai 10 anni e inferiore ai 27, così da ottenere questo risultato:
[['cane', 12], ['gatto', 14], ['aquila', 25]]
[130]:
animali = ['cane', 'gatto', 'pellicano', 'scoiattolo', 'aquila']
anni = [12,14,30,6,25]
# scrivi qui
Funzione zip
La funzione zip
prende due liste e produce una sequenza nuova, in cui mette coppie di elementi come tuple (che ricordiamo sono come le liste ma immutabilii), abbinando il primo elemento della prima lista a primo elemento della seconda lista, il secondo elemento della prima lista al secondo elemento della secondo e così via :
[131]:
list(zip(['a','b','c'], [5,2,7]))
[131]:
[('a', 5), ('b', 2), ('c', 7)]
Perchè abbiamo messo anche list
nell’esempio? Perchè zip
ha lo stesso problema della map
, cioè non materializza subito una lista come forse vorremmo:
[132]:
zip(['a','b','c'], [5,2,7])
[132]:
<zip at 0x7f3ba80fe8c0>
✪✪✪ ESERCIZIO: Come vedi con la zip
abbiamo ottenuto un risultato simile a quello del precedente esercizio, ma abbiamo tuple con parentesi tonde invece di liste con parentesi quadre. Riusciresti aggiungendo una list comprehension
o una map
ad ottenere lo stesso identico risultato?
per convertire una tupla in una lista, usa la funzione
list
:
[133]:
list( ('ciao', 'soft', 'python') ) # all'interno abbiamo messo una tupla, delimitata da parentesi tonde
[133]:
['ciao', 'soft', 'python']
[134]:
animali = ['cane', 'gatto', 'pellicano', 'scoiattolo', 'aquila']
anni = [12,14,30,6,25]
# scrivi qui - soluzione con list comprehension
[135]:
animali = ['cane', 'gatto', 'pellicano', 'scoiattolo', 'aquila']
anni = [12,14,30,6,25]
# scrivi qui - soluzione con map
✪✪✪ ESERCIZIO: svolgi l’esercizio precedente filtrando gli animali con aspettativa di vita superiore ai 13 anni, usando la zip
e una list comprehension
[136]:
animali = ['cane', 'gatto', 'pellicano', 'scoiattolo', 'aquila']
anni = [12,14,30,6,25]
# scrivi qui
✪✪ ESERCIZIO: Date le due liste con nomi di animali e corrispondente aspettativa di vita in anni come sopra, scrivere nella cella sotto del codice che con un normale ciclo for
generi un dizionario che associa alla specie l’aspettativa di vita, così:
{
'aquila': 25,
'cane': 12,
'gatto': 14,
'pellicano': 30,
'scoiattolo': 6
}
ATTENZIONE: l’ordine non ha importanza!
A seconda della versione esatta di Python che avete e di come il dizionario viene creato, l’ordine dei campi quando viene stampato potrebbe differire dall’esempio. Questo è perfettamente normale, perchè le chiavi di un dizionario sono da intendersi come un insieme senza ordine particolare. Se volete essere sicuri di trovare le chiavi stampate nell’ordine in cui sono state inserite, dovete usare un OrderedDict
[137]:
animali = ['cane', 'gatto', 'pellicano', 'scoiattolo', 'aquila']
anni = [12,14,30,6,25]
# scrivi qui
Per ottenere lo stesso risultato in una linea, è possibile usare la funzione zip
come fatto negli esercizi precedenti, e poi la funzione dict
che crea un dizionario a partire dalla lista di coppie di elementi generata dallo zip
:
[138]:
dict(zip(animali, anni))
[138]:
{'cane': 12, 'gatto': 14, 'pellicano': 30, 'scoiattolo': 6, 'aquila': 25}
✪✪ ESERCIZIO: Data una lista di prodotti contenente a sua volta liste ciascuna con categoria, marca e quantità di confezioni vendute:
vendite = [
['pomodori', 'Santini', 5],
['pomodori', 'Cirio', 1],
['pomodori', 'Mutti', 2],
['cereali', 'Kelloggs', 3],
['cereali', 'Choco Pops', 8],
['cioccolata','Novi', 9],
['cioccolata','Milka', 4],
]
Usando un normale ciclo for
, scrivi del codice Python nella cella sotto per creare un dizionario in cui le chiavi sono le categorie e i valori sono la somma delle confezioni vendute per quella categoria:
{
'cereali': 11,
'cioccolata': 13,
'pomodori': 8
}
SUGGERIMENTO: fare attenzione ai due casi, quando il dizionario da ritornare ancora non contiene la categoria estratta dalla lista correntemente in esame e quando invece già la contiene:
Mostra soluzione[139]:
vendite = [
['pomodori', 'Santini', 5],
['pomodori', 'Cirio', 1],
['pomodori', 'Mutti', 2],
['cereali', 'Kelloggs', 3],
['cereali', 'Choco Pops', 8],
['cioccolata','Novi', 9],
['cioccolata','Milka', 4],
]
# scrivi qui
Approfondimenti
Strumenti e script: Se vuoi approfondire come eseguire il codice in editor diversi da Jupyter e avere un’idea più precisa dell’architettura di Python, ti invitiamo a leggere Strumenti e script
Gestione errori e testing: Per capire come si gestiscono le situazioni di errore in genere guarda il foglio separato Gestione errori e testing, serve anche per capire come eseguire alcuni esercizi della Part A - Fondamenti.