Sei sulla pagina 1di 7

Lezione "sperimentale"

Correzione esercizi scorsa lezione


Ripartiamo dagli esercizi della volta scorsa. Innanzitutto ho due
commenti generali:

Per convenzione, i nomi delle funzioni iniziano con una


lettera minuscola e, se sono composti da più parole,
soltanto quelle successive alla prima iniziano con la lettera
maiuscola, per esempio:

def funzioneCheRispettaLeConvenzioni():
pass

I testi dei vari esercizi erano tutti del tipo: “Scrivi una
funzione che prende in input due numeri” oppure “una lista
di numeri” oppure “un numero intero”… Hai provato ad
eseguire i tuoi programmi passando alle varie funzioni, per
esempio, una stringa al posto di un numero, o una lista al
posto di un numero? Ti suggerisco un po’ di esperimenti e
aggiustamenti da fare:

Prova ad eseguire la funzione MaggioreDi()


dell’esercizio 1 passandole non due numeri, ma due
stringhe. Cosa succede? C’è un messaggio di errore?

Fai lo stesso esperimento passando alla funzione un


numero ed una stringa. Cosa succede adesso?
Prova con due liste, due tuple e tutti gli altri tipi che ti
vengono in mente. Segnati eventuali messaggi di errore
e altre stranezze che non capisci.

Riscrivi la funzione MaggioreDi() in modo che, prima di


confrontare i due valori in input, controlli che siano del
tipo giusto. Il ragionamento è lo stesso anche per tutti gli
altri esercizi, ma non c’è bisogno che li correggi tutti
quanto, ne basta uno a titolo di esempio. Indizio: puoi
usare la funzione type() . Ecco un esempio del suo
funzionamento:

>>> if type(45) == int: print("E' un intero")


...
"E' un intero"

Puoi trovare altre informazioni qui.

Ora alcuni commenti sui singoli esercizi:

1. OK

2. La prima versione, che confronta due tuple, ha senso,


anche se non era quelo che intendevo. La seconda ha il
difetto che prende in input due numeri, non una tupla.
Un esempio di soluzione potrebbe essere

def maggioreDellaTupla(t):
  (a,b) = t # la tupla viene "spacchettata"
   # il resto è simile al primo esercizio
   if a > b: return a
   return b
3. E’ un po’ più complicato del necessario e soprattutto
funziona solo per liste di una certa lunghezza. Prova a
rifare questo esercizio. Lo stesso errore è stato fatto
anche nell’esercizio 5 e nel 6. Osserva questa soluzione:

def maggioreDellaLista(l):
   m = l[0] # provvisoriamente, diciamo che
il primo elemento della lista è il maggiore e
salviamolo in una variabile m
   for e in l:
       if e > m: m = e # nel momento in cui
troviamo un valore di quelo salvato in m,
aggiorniamo la variabile m con tale valore
   return m # restituiamo m

Solo se il ragionamento ti è chiaro, prova ad applicarlo


anche agli esercizi 5 e 6

4. OK

5. Vedi 3

6. Vedi 3, ma ricordami anche di farti ragionare su una cosa


molto interessante che hai scritto nella tua soluzione.

Ricorsione
L’argomento di cui volevo parlarti oggi è la ricorsione, che è
un concetto fondamentale della programmazione, anche se
all’inizio potrebbe risultare un po’complicato da utilizzare.

Abbiamo già visto che una funzione può, al suo interno,


chiamarne altre. Per esempio:
def sommaUnoAlMaggiore(a,b):
   return 1 + maggioreDi(a,b)

è una funzione che individua il maggiore tra due numeri e


gli somma 1.

Non c’è dunque motivo per cui una funzione non possa
chiamare sé stessa (questo è appunto il fenomeno che si
chiama ricorsione). Immaginiamo di voler scrivere una
funzione che fa il conto alla rovescia a partire da un certo
numero in input, ma di non avere a disposizione né il ciclo
for né il ciclo while , ma solo gli if . Per risolvere questo
problema apparentemente difficile, basta scrivere una
funzione ricorsiva, cioè appunto una funzione che chiama sè
stessa:

def contoAllaRovescia(n):
   if n <= 0:
       print("Pronti al decollo!") # frase a
caso
   else:
       print n
       contoAllaRovescia(n - 1) # ricorsione:
chiamiamo la funzione contoAllaRovescia stessa
(ma con un argomento diverso)

Parentesi: perché far finta che non esistano i cicli?


Risposta breve: perché non sono necessari, e talvolta
nemmeno comodi. Il linguaggio che uso tutti i giorni da
un anno a questa parte non li ha, e se è per questo non
ha nemmeno le variabili, ma questa è un’altra storia.
Esercizio facile facile: copia e incolla il codice sopra su
un file python e prova ad eseguirlo, poi scrivi una
funzione che fa esattamente la stessa cosa, ma come
avresti fatto normalmente, con un ciclo for o while

La definizione di contoAllaRovescia(n) è divisa


fondamentalmente in due parti, o casi:

il cosiddetto caso base, ossia il caso in cui si esce dalla


ricorsione (che corrisponde, se invece ragionassimo per
cicli, all’iterazione in cui si esce dal ciclo), che nel nostro
esempio è il corpo dell’ if
il caso ricorsivo, cioè il caso in cui chiamiamo la stessa
funzione che stiamo definendo.

Quando si scrive una funzione ricorsiva è bene fare


particolare attenzione al caso base: se, nel nostro esempio,
n non arrivasse mai ad essere minore o uguale a zero, la
funzione verrebbe eseguita all’infinito (il che, generalmente,
è bene evitare).

Parentesi: quello che ho detto sulla ricorsione infinita


non è proprio vero (anche se è vero per quasi tutti i
linguaggi di programmazione). Prova ad eseguire queste
due funzioni, entrambe “infinite”, e vedrai che
l’interprete del python, almeno nei casi più semplici, è in
grado di individuare le ricorsioni infinite, mentre non è
in grado di bloccare un ciclo infinito:
def ricorsione():
   ricorsione()
   
def iterazione():
   while True:
       pass

Per oggi, questo è tutto. Questo concetto di ricorsione è


abbastanza difficile da padroneggiare ci terrà impegnati,
penso, per qualche lezione di seguito. Se però ti senti sicuro,
hai tempo e hai voglia, prova anche questo esercizio:

Esercizio difficile: La funzione che segue cerca un


elemento in una lista e restituisce il suo indice (cioè la
posizione nella lista) se l’elemento è presente nella lista,
False altrimenti.

def cercaIterativo(a,lista):
n = len(lista)
for i in range(n):
  if lista[i] == a:
    return i
return False

leggi attentamente il codice, cerca di capirlo bene, e prova a


riscrivere la stessa funzione in modo ricorsivo ( for e
while sono vietati!). Se trovi delle difficoltà, non
preoccuparti: questo algoritmo, che si chiama ricerca lineare
(abbiamo mai parlato di cosa è un algoritmo?) è più facile
da esprimere coi cicli che con la ricorsione. La prossima
volta, ti farò vedere il caso opposto: un algoritmo che è più
semplice scrivere ricorsivamente e che, tra l’altro, è anche
più efficiente.