Indeterminata,,,... Università di Bologna 14, 16 marzo 2012
Sommario 1 2 3 4 5
Modularità Quando si deve fare un programma complicato è meglio suddividerlo in più parti. Per ridurre la complessità (più facile da scrivere). E per facilitare la ricerca di eventuali errori (debugging). Analogia: dividere un teorema in lemmi.
Leggere da tastiera I dati che può utilizzare un programma possono essere: contenuti nel programma stesso o variabili globali; gli argomenti passati ad una funzione; oppure dati richiesti durante l esecuzione dal programma stesso. Per chiedere all utente di inserire dei dati si utilizza raw_input (legge una stringa). def QuantoFa(): n=int(raw_input('quanto fa 2*3? ')) if n==6: print 'Giusto!' else: print 'Sbagliato.'
Modificare variabili Python ha modi compatti di modificare il valore di una variabile della forma variabile operatore-aritmetico = espressione. i+=3 i-=3 i*=3 i/=3 i=i+3 i=i-3 i=i*3 i=i/3
Argomenti Opzionali def Ciao(nome='Pinco Pallino'): print 'Ciao '+str(nome)+'!' Eseguendo Ciao() (senza argomenti) viene usato il valore predefinito.
Ciclo while In alternativa al for, si possono iterare dei comandi usando un ciclo while. def GrazieMolte(n): i=0 while i<n: print 'Grazie!' i=i+1 Indicato per quando non si sa quante iterazioni bisogna fare. Per iterare finché vale una certa condizione (o cercare un elemento che non la soddisfi).
break & continue Controllare comportamento ciclo for o while con break e continue. def TrovaTriplo1(n): def TrovaTriplo2(n): i=n i=n while True: while i%3: #inizio ciclo i=i+1 if i%3: print i i=i+1 continue #vai inizio break #vai fuori #fuori dal ciclo print i continue interrompe l iterazione corrente e passa alla successiva. break interrompe l iterazione corrente ed esce dal ciclo (salta ogni altra iterazione residua).
Funzioni NoneType & return Funzioni viste finora non calcolano nulla. Stampano solo a video. def HelloWorld1(): print 'Hello World!' def HelloWorld2(): print 'Hello World!' return In realtà: type(helloworld1()) = <type 'NoneType'>. Si tratta di un tipo speciale che si usa per funzioni in cui non compare un istruzione return o se questa è vuota. Se una funzione calcola qualcosa si usa return per restituire il valore all esterno. NoneType è un tipo speciale utile per restituire errore. type(none) = NoneType
& return Usiamo return per definire una funzione che calcola qualcosa ( fruitful nel gergo di Think Python). Calcoliamo la parte intera della radice quadrata di un intero n. Dividiamo il procedimento in più parti: Precondizione n deve essere non-negativo. Prima approssimazione si trova la massima potenza di 2 il cui quadrato non supera n. Approssimazioni successive si sommano ad essa le potenze di 2 inferiori (fino ad 1 = 2 0 ) in modo che il quadrato di questa somma non superi n. Per approfondimenti: http://freaknet.org/martin/tape/ gos/misc/personal/msc/sqrt/sqrt.html.
& return Usiamo return per definire una funzione che calcola qualcosa ( fruitful nel gergo di Think Python). Calcoliamo la parte intera della radice quadrata di un intero n. Dividiamo il procedimento in più parti: Precondizione n deve essere non-negativo. Prima approssimazione si trova la massima potenza di 2 il cui quadrato non supera n. Approssimazioni successive si sommano ad essa le potenze di 2 inferiori (fino ad 1 = 2 0 ) in modo che il quadrato di questa somma non superi n. Per approfondimenti: http://freaknet.org/martin/tape/ gos/misc/personal/msc/sqrt/sqrt.html.
& return Usiamo return per definire una funzione che calcola qualcosa ( fruitful nel gergo di Think Python). Calcoliamo la parte intera della radice quadrata di un intero n. Dividiamo il procedimento in più parti: Precondizione n deve essere non-negativo. Prima approssimazione si trova la massima potenza di 2 il cui quadrato non supera n. Approssimazioni successive si sommano ad essa le potenze di 2 inferiori (fino ad 1 = 2 0 ) in modo che il quadrato di questa somma non superi n. Per approfondimenti: http://freaknet.org/martin/tape/ gos/misc/personal/msc/sqrt/sqrt.html.
& return Usiamo return per definire una funzione che calcola qualcosa ( fruitful nel gergo di Think Python). Calcoliamo la parte intera della radice quadrata di un intero n. Dividiamo il procedimento in più parti: Precondizione n deve essere non-negativo. Prima approssimazione si trova la massima potenza di 2 il cui quadrato non supera n. Approssimazioni successive si sommano ad essa le potenze di 2 inferiori (fino ad 1 = 2 0 ) in modo che il quadrato di questa somma non superi n. Per approfondimenti: http://freaknet.org/martin/tape/ gos/misc/personal/msc/sqrt/sqrt.html.
Esempio Fruitful Radice quadrata e due funzioni ausiliarie def intok(n): b1=isinstance(n,int) b2=n>=0 return b1 and b2 def potenzamax(n): if not(intok(n)): return None i=1 j=0 while i**2<=n: j=i i=i*2 return j def sqrt(n): if not(intok(n)): return None else: j=potenzamax(n) radice=0 r=0 while j>0: r=radice+j if r**2<=n: radice=r j=j/2 return radice
Slice Possiamo selezionare un segmento di una stringa in analogia a come selezioniamo un carattere: 1 s='mario Monti' 2 s[3] = 'i' 3 s[3:7] = 'io M'. Analogo uso per liste e tuple. Argomento opzionale per procedere a passi di più caratteri/elementi (come per range) 4 s[0:5:2] = 'Mro'. 5 Si usa anche per leggere una stringa a rovescio: s[::-1] = 'itnom oiram'. 6 Posso usare le slice per copiare una stringa in un altra s2=s[::] o semplicemente s2=s[:]. 7 Se invece scrivo s2=s, ho due nomi per la stessa cosa (aliasing). Non importante per stringhe e tuple (per le liste sì, sono modificabili).
Modulo string Con il comando import string si carica il modulo string che contiene una serie di costanti e di metodi utili per lavorare con le stringhe. 1 s= Esempio 2 import string 3 s.upper() (= ESEMPIO ) 4 s.lower() (= esempio ) 5 string.lowercase (= abcdefghijklmnopqrstuvwxyz ) 6 string.uppercase (= ABCDEFGHIJKLMNOPQRSTUVWXYZ ) 7 string.digits (= 0123456789 ) 8 string.punctuation (= '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{ }~') def NoLettere(s): return s.upper()==s.lower()
Idea della ricorsione: ridurre un calcolo complesso a un caso semplice, che si sa risolvere direttamente, e costruire a ritroso il risultato del calcolo originario. Come? Una funzione che invoca se stessa, su elementi più piccoli. Devono esistere uno o più casi base a cui ricondursi, altrimenti l esecuzione non termina (ricorsione infinita). In pratica Python darà errore (si arriva ad un caso in cui la funzione non è definita o si raggiunge la profondità massima di ricorsione consentita). def semifact(n): if n==0 or n==1: return 1 else: return n*semifact(n-2)
Altro esempio Usando le slice possiamo calcolare la lunghezza di una successione (lista, tupla o stringa). def mylen(s): if s==[] or s==() or s='': return 0 else: return 1+mylen(s[1:]) Python ha già una funzione per questo chiamata len.
Esercizi in laboratorio 1 Calcolare l n-simo elemento della successione di Fibonacci. 2 Calcolare il valore di un polinomio p(x) in un punto a usando la regola di Horner. 3 Data una stringa s determinare se è un palindromo. 4 Data una stringa s determinare se è una password sicura: deve contenere sia lettere (sia maiuscole che minuscole) che cifre e deve essere lunga almeno dieci caratteri).
Suggerimenti 1 F 0 = 0, F 1 = 1, F n+1 = F n + F n 1. 2 Rappresentare un polinomio p come una tupla in cui in posizione i c è il coefficiente i-simo di p. Regola di Horner: http://en.wikipedia.org/wiki/horner s_method. 3 Confrontare la prima e l ultima lettera della parola e ridursi ai casi in cui s ha uno o zero caratteri. 4 Usare l operatore in e il modulo string.
Primo esercizio def fibonacci(n): if n==0 or n==1: return n else: return fibonacci(n-1)+fibonacci(n-2) Per prima cosa scaliamo di uno l indice della formula e otteniamo F n = F n 1 + F n 2, n > 1. A questo punto il passaggio in Python è diretto.
Secondo esercizio def horner(p,x): n=len(p) if n==0: return 0 elif n==1: return p[0] else: return p[0]+x*horner(p[1:],x) Nel caso base il polinomio è una costante, che è anche il valore in x (come caso particolare il polinomio nullo può essere rappresentato anche da una tupla vuota). Sappiamo che a 0 + a 1 x + a 2 x 2 + + a n 1 x n 1 + a n x n = a 0 + x(a 1 + a 2 x + + a n 1 x n 2 + a n x n 1 ). Quindi negli altri casi applichiamo il metodo al polinomio rappresentato dalla tupla privata del primo elemento (corrisponde a prendere il polinomio originale, togliere il termine noto e raccogliere x) e poi moltiplichiamo il risultato per x e ri-aggiungiamo il termine noto.
Terzo esercizio Soluzione ricorsiva def palindromorec(s): n=len(s) if n==0 or n==1: return True else: return s[0]==s[n-1] and palindromo(s[1:n-1]) Le stringhe di zero o un carattere sono palindrome. Se il primo e l ultimo carattere coincidono la stringa è un palindromo se e solo se la stringa ottenuta togliendo quei due caratteri è un palindromo. Se il primo e l ultimo carattere sono diversi, l and valuta a False qualunque sia palindromo(s[1:n-1]) (che in tal caso non viene calcolato).
Terzo esercizio Soluzione diretta def palindromo(s): return s==s[::-1] Una stringa è un palindromo se e solo se è invariante per riflessione. Questo caso è più semplice che usare la ricorsione. Intanto impariamo ad utilizzare le varie tecniche per risolvere un dato problema, poi con l esperienza capiamo quale conviene utilizzare a seconda dei casi.
Quarto esercizio Vedi 4 laboratorio.