# Tutorial per newbies con Python

### Josh Cogliati

Copyright © 1999-2001 Josh Cogliati

Permission is granted to anyone to make or distribute verbatim copies of this document as received, in any medium, provided that the copyright notice and permission notice are preserved, and that the distrubutor grants the recipient permission for further redistribution as permitted by this notice.

Permission is granted to distribute modified versions of this document, or of portions of it, under the above conditions, provided also that they carry prominent notices stating who last altered them.

All example python source code in this tutorial is granted to the public domain. Therefore you may modify it and relicence it under any license you please.

Josh Cogliati: http://www.honors.montana.edu/~jjc/easytut/easytut/ `<jjc@honors.montana.edu>`

Versione in lingua Italiana del "Non-Programmers Tutorial For Python" a cura di Nicholas Wieland e Ferdinando Ferranti.

Per quanto riguarda eventuali aggiornamenti della versione Italiana rivolgersi a: `<gregorsamsa@email.it>` o `<zappagalattica@inwind.it>`, i successivi aggiornamenti di questa traduzione dovrebbero essere reperibili o raggiungibili dal sito locale di Python: http://www.python.it

Diario delle revisioni
Revisione 1.0 | 25 agosto 2002 | Corretto da: Nicholas W. e Ferdinando F.

# Dedica

Dedicato a Elizabeth Cogliati.

Lista delle Tabelle
2-1.
5-1.
6-1.
8-1.
8-2.
10-1.
10-2.
10-3.

# Prefazione

"Tutorial di Python per newbies" è un tutorial pensato per essere una introduzione alla programmazione in Python, è destinato infatti a chi non ha esperienze con la programmazione.

Se qualcuno di voi ha già programmato con altri linguaggi vi raccomando il Python Tutorial scritto da Guido van Rossum.

Se qualcuno di voi ha domande o commenti mi contatti al mio indirizzo `<jjc@iname.com>`, (`<gregorsamsa@email.it>` per la presente versione tradotta) commenti e suggerimenti riguardo questo documento sono i benvenuti. Proverò a rispondere a qualsiasi domanda poniate meglio che potrò.

I ringraziamenti vanno a James A. Brown per aver scritto la maggior parte della sezione dedicata all'installazione sotto Windows. Grazie anche a Joe Oppergaard per aver scritto tutti gli esercizi. Grazie anche a tutti quelli che ho dimenticato.

# Capitolo 1. Introduzione

## La prima cosa

Se state leggendo questo tutorial non avete mai programmato in vita vostra. Proseguite nella lettura e tenterò di insegnarvi come si programma. Innanzitutto chiarezza: c'è una sola via da percorrere per imparare a programmare, leggere codice - scrivere codice e io ve ne farò leggere e scrivere tantissimo. Per questo dovrete sempre scrivere il codice degli esempi ed eseguirlo per poi vedere che cosa succede: giocate con il codice, modificatelo come volete, la cosa peggiore che può capitarvi è che il programma non funzioni. Per riconoscere il codice dalla normale scrittura userò questo formato:

>     ##Python is easy to learn
>     print "Hello, World!"

Facile da distinguere dal resto del testo no ? Appunto per confondervi scriverò così anche gli outputs del computer :=)

Un'altra cosa importante: per programmare in Python vi serve il Python. Se non avete ancora il software necessario dirigetevi verso http://www.python.org/download. Andate alla versione 2.0 o superiore e scaricatevi la versione adatta alla vostra piattaforma, leggete le istruzioni e installatela.

## Installare Python

Innanzitutto scaricatevi il file appropriato: il Windows Installer nel caso usiate Windows o i sorgenti da compilare se avete un sistema Unix.

Scaricando il Windows Installer avrete un file che basterà doppiocliccare per iniziare la procedura di installazione.

Scaricando i sorgenti Unix assicuratevi di compilare con l'estensione Tk per usare IDLE.

## Modo interattivo

Aprite IDLE, la GUI di Python. Dovreste vedere una finestra di questo tipo:

>     Python 2.2b1 (#1, Nov  4 2001, 01:38:44)
>     [GCC 2.95.4 20011006 (Debian prerelease)] on linux2
>     Type "copyright", "credits" or "license" for more information.
>     IDLE 0.8 -- press F1 for help
>     >>>

>>> è il modo che ha Python per informarvi che siete in modo interattivo, dove i comandi digitati sono immediatamente eseguiti. Provate a digitare 1+1 e Python vi risponderà immediatamente 2. In questa modalità potete provare e vedere come reagisce Python ai vari comandi. Usatela quando sentirete il bisogno di prendere confidenza con i comandi Python.

## Creare ed eseguire programmi

Andate in modo interattivo se non ci siete già. Selezionate File dal menu dopodiché selezionate New Window.

Digitate nella nuova finestra il seguente testo (codice):

>     print "Hello, World!"

Innanzitutto salvate il programma sempre selezionando dal menu `File` e poi `Save`. Salvatelo come "hello.py" nella directory di default o nella directory che preferite. Ora che avete salvato potete eseguire il programma. Selezionate dal menu la voce `edit` e poi `Run script`. Questa azione vi restituirà l'output richiesto dal programma hello.py nella finestra `*Python Shell*` che saluterà allegramente con un: `Hello, World!`.

## Usare Python dalla linea di comando

Se preferite non utilizzare Python dalla linea di comando non siete obbligati, usate IDLE.

Per entrare in modo interattivo dalla linea di comando dovete semplicemente digitare python mentre se volete eseguire un programma scritto con un editor di testo (ad esempio Emacs è un ottimo editor per Python) non dovete fare altro che usare la sintassi `python program name`.

# Capitolo 2. Hello, World

## Cosa dovresti già sapere

Dovresti sapere come visualizzare un programma in un editor di testo, salvarlo su disco (floppy o disco fisso) ed eseguirlo una volta salvato.

## Stampare

Sin dall'inizio dei tempi i tutorials sono sempre iniziati con un semplice programma chiamato 'Hello World'. Eccolo:

>     print "Hello, World!"

Se state usando la linea di comando per eseguire i programmi inserite la linea di testo in un editor e salvate come 'hello.py', eseguite il file appena salvato con il comando 'python hello.py'.

Altrimenti entrate in IDLE, aprite una nuova finestra (New window) e create il programma come spiegato nella sezione 1.3.

Ecco cosa stampa sullo schermo 'hello.py' quando viene eseguito:

>     Hello, World!

Non ve lo dirò ogni volta ma vi consiglio vivamente di ripetere tutti gli esercizi che vi mostro, questo vi aiuterà a comprenderli meglio, anch'io imparo di più quando scrivo, probabilmente anche voi ...

Tentiamo un programma un po' più complicato:

>     print "Jack and Jill went up a hill"
>     print "to fetch a pail of water;"
>     print "Jack fell down, and broke is crown,"
>     print "and Jill came tumbling after."

Quando eseguirete il programma l'output sul monitor sarà questo:

>     Jack and Jill went up a hill
>     to fetch a pail of water;
>     Jack fell down, and broke his crown,
>     and Jill came tumbling after.

Quando il computer esegue questo programma vede innanzitutto la prima riga:

>     print "Jack and Jill went up a hill"

Ed esegue l'ordine, ovvero stampa:

>     Jack and Jill went up a hill

Dopodiché il computer prosegue a leggere il codice e passa alla seconda linea:

>     	print "to fetch a pail of water;"

Il risultato è la stampa di:

>     to fetch a pail of water;

Capito il meccanismo? Il computer continua a scendere di linea in linea seguendo e svolgendo le istruzioni che voi stessi gli ordinate finché non raggiunge la fine del programma.

## Espressioni

Ecco qui un'altro programma:

>     print "2 + 2 is ", 2 + 2
>     print "3 * 4 is ", 3 * 4
>     print 100-1, " = 100 - 1"
>     print "(33 + 2) / 5 + 11.5 = ", (33 + 2) / 5 + 11.5

E qui l'output che questo programma produce:

>     2 + 2 is 4
>     3 * 4 is 12
>     99 = 100 - 1
>     (33 + 2) / 5 + 11.5 =  18.5

Come puoi vedere Python può trasformare il vostro costosissimo computer in una normale calcolatrice :-)

Python ha 6 operatori basilari:

Tabella 2-1.

Operazione | Simbolo | Esempio
--- | --- | ---
Elevamento a potenza | ** | 5 ** 2 = 25
Moltiplicazione | * | 2 * 3 == 6
Divisione | / | 14 / 3 == 4
Resto | % | 14 % 3 == 2
Addizione | + | 1 + 2 == 3
Sottrazione | - | 4 - 3 == 1

Osservate come la divisione segua la regola per cui se nel dividendo e nel divisore non sono presenti decimali anche il risultato non conterrà decimali (questo però cambierà in Python 2.3).

Il seguente programma dimostra la regola appena enunciata:

>     print "14 / 3 = ",14 / 3
>     print "14 % 3 = ",14 % 3
>     print
>     print "14.0 / 3.0 =",14.0 / 3.0
>     print "14.0 % 3.0 =",14 % 3.0
>     print
>     print "14.0 / 3 =",14.0 / 3
>     print "14.0 % 3 =",14.0 % 3
>     print
>     print "14 / 3.0 =",14 / 3.0
>     print "14 % 3.0 =",14 % 3.0
>     print

Con l'output:

>     14 / 3 =  4
>     14 % 3 =  2

>     14.0 / 3.0 = 4.66666666667
>     14.0 % 3.0 = 2.0

>     14.0 / 3 = 4.66666666667
>     14.0 % 3 = 2.0

>     14 / 3.0 = 4.66666666667
>     14 % 3.0 = 2.0

Python da risposte differenti in base alla presenza o meno di numeri decimale.

L'ordine delle operazioni è lo stesso che nella matematica:

1. parentesi ()

2. potenza **

3. moltiplicazione *, divisione / e resto %

4. addizione + e sottrazione -

## Parlare agli umani (e ad altri esseri intelligenti)

Vi capiterà sicuramente, quando sarete più esperti, di dover programmare applicazioni molto complesse e lunghe. Difficilmente rileggendo il codice dopo qualche tempo riuscirete a ricordarvi tutti i passaggi e tutti i ragionamenti fatti, per questo è meglio che prendiate da subito l'abitudine di commentare il vostro lavoro.

Un commento è semplicemente una nota, per altri programmatori ma anche per voi stessi, che spiega il programma nei punti salienti. Ad esempio:

>     #Not quite PI, but an incredible simulation
>     print 22.0 / 7.0

Come potete vedere il commento inizia con il simbolo #.

## Esempi

Ogni capitolo conterrà esempi delle proprietà di programmazione introdotte nel capitolo stesso. Dovreste almeno dare un'occhiata al codice per vedere se riuscite a capirlo. Nel caso alcuni passaggi non fossero chiari potete scrivere il codice ed eseguirlo per tentare di capirlo meglio o addirittura apportare delle modifiche per vedere cosa succede

Denmark.py

>     print "Something's rotten in the state of Denmark."
>     print "                -- Shakespeare"

Output:

>     Something's rotten in the state of Denmark.
>                            -- Shakespeare

School.py

>     #This is not quite true outside of USA
>     # and is based on my dim memories of my younger years
>     print "Firstish Grade"
>     print "1+1 =",1+1
>     print "2+4 =",2+4
>     print "5-2 =",5-2
>     print
>     print "Thirdish Grade"
>     print "243-23 =",243-23
>     print "12*4 =",12*4
>     print "12/3 =",12/3
>     print "13/3 =",13/3," R ",13%3
>     print
>     print "Junior High"
>     print "123.56-62.12 =",123.56-62.12
>     print "(4+3)*2 =",(4+3)*2
>     print "4+3*2 =",4+3*2
>     print "3**2 =",3**2
>     print

Output:

>     Firstish Grade
>     1+1 = 2
>     2+4 = 6
>     5-2 = 3

>     Thirdish Grade
>     243-23 = 220
>     12*4 = 48
>     12/3 = 4
>     13/3 = 4  R  1

>     Junior High
>     123.56-62.12 = 61.44
>     (4+3)*2 = 14
>     4+3*2 = 10
>     3**2 = 9

## Esercizi

Scrivete un programma che stampa su schermo il vostro nome e cognome con due stringhe separate.

Scrivete un programma che mostra l'utilizzo delle 6 operazioni matematiche.

# Capitolo 3. Chi va là ?

## Input e variabili

Ora proviamo un programma un po' più complicato:

>     print "Halt!"
>     s = raw_input("Who Goes there? ")
>     print "You may pass,", s

ecco l'output del programma:

>     Halt!
>     Who Goes there? Josh
>     You may pass, Josh

Ovviamente quando proverete anche voi l'esecuzione il vostro output sarà differente grazie all'espressione `raw_input.` Avviando il programma (perché lo state provando vero?) avrete notato che richiede l'inserimento del vostro nome per poi premere 'Enter' e continuare l'esecuzione; a quel punto viene visualizzato un messaggio seguito dal vostro nome. Questo è un esempio di input: il programma viene eseguito fino a un certo punto, dopodiché attende un input di dati dall'utente.

Certamente un input sarebbe inutile se non avessimo nessun posto dove mettere l'informazione ottenuta, ecco quindi che entrano in gioco le variabili. Nel programma precedente `s` è, appunto, una variabile. Le variabili sono come delle scatole in cui si possono immagazzinare dati. Ecco un programma che ne spiega l'utilizzo:

>     a = 123.4
>     b23 = 'Spam'
>     first_name = "Bill"
>     b = 432
>     c = a + b
>     print "a + b is", c
>     print "first_name is", first_name
>     print "Sorted Parts, After Midnight or",b23

e questo è l'output:

>     a + b is 555.4
>     first_name is Bill
>     Sorted Parts, After Midnight or Spam

Come ho detto: le variabili immagazzinano dati. Nel programma qui sopra ad esempio sono `a, b23, first_name, b` e `c`. Le due tipologie base di variabili sono stringhe e numeri. Le stringhe sono sequenze di lettere, numeri e altri caratteri: nell'esempio `b23` e `first_name` sono variabili contenenti stringhe. `'Spam', 'Bill', 'a + b is '` e `'first_name'` sono stringhe: come potete notare sono sempre racchiuse da " ' " o " " ". Gli altri tipi di variabili presenti sono numeri.

Ora, abbiamo queste scatole chiamate variabili e anche dati da metterci dentro. Il computer vedrà una linea come `'first_name = Bill'` che leggerà come - metti la stringa `'Bill'` nella scatola (o variabile) `'first_name'`. Più tardi vedrà l'espressione `'c = a + b'` che leggerà come "metti `a+b` o 123.4 + 432 all'interno della variabile `c`".

Ecco un'altro esempio sull'utilizzo delle variabili:

>     a = 1
>     print a
>     a = a + 1
>     print a
>     a = a * 2
>     print a

E di conseguenza ecco l'output:

>     1
>     2
>     4

Anche se in tutti i casi sopraelencati la variabile ha lo stesso nome il computer la rilegge ogni volta. Prima trova i dati da immagazzinare e poi trova dove immagazzinarli.

Un'ultimo esempio prima di chiudere il capitolo:

>     num = input("Type in a Number: ")
>     str = raw_input("Type in a String: ")
>     print "num =", num
>     print "num is a ",type(num)
>     print "num * 2 =",num*2
>     print "str =", str
>     print "str is a ",type(str)
>     print "str * 2 =",str*2

Ecco l'output che ho ottenuto:

>     Type in a Number: 12.34
>     Type in a String: Hello
>     num = 12.34
>     num is a  <type 'float'>
>     num * 2 = 24.68
>     str = Hello
>     str is a  <type 'string'>
>     str * 2 = HelloHello

Osserva il modo in cui ho ottenuto dall'utente le due varaibili: input per la variabile numerica e `raw_input` per la variabile stringa. Quando volete che l'utente inserisca un numero o una stringa utilizzate, rispettivamente, input o stringa `raw_input`.

La seconda parte del programma utilizza la funzione type che vi informa sul tipo di variabile: le varibili numeriche sono di tipo int (numero intero) o float (numero decimale), le stringhe sono di tipo string. Interi e decimali possono essere utilizzati per operazioni matematiche, le stringhe no. Tuttavia quando una stringa viene moltiplicata per un intero vengono aggiunte alla stringa copie di se stessa: ad es. `str * 2 = HelloHello`

## Esempi

rate_times.py

>     #This programs calculates rate and distance problems
>     print "Input a rate and a distance"
>     rate = input("Rate:")
>     distance = input("Distance:")
>     print "Time:",distance/rate

Esecuzione:

>     > python rate_times.py
>     Input a rate and a distance
>     Rate:5
>     Distance:10
>     Time: 2
>     > python rate_times.py
>     Input a rate and a distance
>     Rate:3.52
>     Distance:45.6
>     Time: 12.9545454545

area.py

>     #This program calculates the perimeter and area of a rectangle
>     print "Calculate information about a rectangle"
>     length = input("Length:")
>     width = input("Width:")
>     print "Area",length*width
>     print "Perimeter",2*length+2*width

Esecuzione:

>     > python area.py
>     Calculate information about a rectangle
>     Length:4
>     Width:3
>     Area 12
>     Perimeter 14
>     > python area.py
>     Calculate information about a rectangle
>     Length:2.53
>     Width:5.2
>     Area 13.156
>     Perimeter 15.46

temperature.py

>     #Converts fahrenheit to celcius
>     temp = input("Farenheit temperature:")
>     print (temp-32.0)*5.0/9.0

Esecuzione:

>     > python temperature.py
>     Farenheit temperature:32
>     0.0
>     > python temperature.py
>     Farenheit temperature:-40
>     -40.0
>     > python temperature.py
>     Farenheit temperature:212
>     100.0
>     > python temperature.py
>     Farenheit temperature:98.6
>     37.0

## Esercizi

Scrivete un programma che prenda due variabili stringa e due numeriche intere dall'utente, unisca le due stringhe senza spazi e le visualizzi sullo schermo, infine moltiplichi i due numeri interi su una linea nuova.

# Capitolo 4. Conta da 1 a 10

## Cicli While

Ecco qui finalmente la nostra prima struttura di controllo. Solitamente il computer legge il nostro programma cominciando dalla prima linea per poi scendere da lì fino alla fine del codice. Le strutture di controllo influiscono sul programma cambiando l'ordine d'esecuzione dei comandi o decidendo se un determinato comando verrà eseguito o meno. A voi il sorgente di un primo esempio che utilizza la struttura di controllo '`while`':

>     a = 0
>     while a < 10:
>             a = a + 1
>             print a

Quindi il risultato dell'esecuzione:

>     1
>     2
>     3
>     4
>     5
>     6
>     7
>     8
>     9
>     10

Cosa fa il programma? Prima di tutto vede la linea `'a = 0'` e assegna il valore zero alla variabile numerica `a`. Dopodiché vede il comando `'while a < 10:'` che ordina a Python di controllare se la variabile `a` è minore di 10: in questo caso `a` corrisponde al valore zero quindi è minore di 10, per questo motivo Python eseguirà tutte le istruzioni rientrate sotto la struttura `'while'`. In poche parole finché la variabile numerica `a` è minore di dieci Python esegue tutte le istruzioni tabulate sotto `while`.

Ecco un'altro esempio dell'uso di `while`:

>     a = 1
>     s = 0
>     print 'Enter Numbers to add to the sum.'
>     print 'Enter 0 to quit.'
>     while a != 0
>             print 'Current Sum:',s
>             a = input('Number? ')
>             s = s + a
>     print 'Total Sum =',s

Appena eseguito questo script l'output è stato questo:

>       File "sum.py", line 3
>         while a != 0
>                     ^
>     SyntaxError: invalid syntax

Ho dimenticato il ':' dopo il while. Python avverte dell'errore e mostra all'utente dov'è il problema segnando la linea di codice incriminata con un utile `^`. Dopo aver risolto il problema grazie all'aiuto di Python il programma funziona a meraviglia ed ecco finalmente il risultato:

>     Enter Numbers to add to the sum.
>     Enter 0 to quit.
>     Current Sum: 0
>     Number? 200
>     Current Sum: 200
>     Number? -15.25
>     Current Sum: 184.75
>     Number? -151.85
>     Current Sum: 32.9
>     Number? 10.00
>     Current Sum: 42.9
>     Number? 0
>     Total Sum = 42.9

Come puoi vedere `'print 'Total sum =', s'` è eseguito solamente alla fine: questo perché la struttura di controllo `'while'` influisce solamente sulle istruzioni tabulate (rientrate, indentate). Il simbolo `!=` significa diverso: finché `a` è diverso da zero esegui le istruzioni tabulate sotto `while`.

Ora che abbiamo capito la struttura di controllo `'while'` possiamo programmare uno script che venga eseguito all'infinito. Una via molto facile per farlo è ad esempio questa:

>     while 1 == 1:
>          print "Help, I'm stuck in a loop."

L'output di questo programma sarà una continua ripetizione della frase `'Help, I'm stuck in a loop !!! '` all'infinito, a meno che non lo fermiate premendo i tasti '`Ctrl`' e '`C`' contemporaneamente. Questo manderà un segnale di terminazione al programma.

(Nota: a volte dovrete premere Invio oltre a '`Ctrl+c`')

## Esempi

fibonacci.py

>     #This program calulates the fibonnaci sequence
>     a = 0
>     b = 1
>     count = 0
>     max_count = 20
>     while count < max_count:
>         count = count + 1
>         #we need to keep track of a since we change it
>         old_a = a
>         a = b
>         b = old_a + b
>         #Notice that the , at the end of a print statement keeps it
>         # from switching to a new line
>         print old_a,
>     print

Output:

>     0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181

password.py

>     # Waits until a password has been entered.  Use control-C to break out with out
>     # the password

>     password = "foobar"

>     #note that != means not equal
>     while password != "unicorn":
>         password = raw_input("Password:")
>     print "Welcome in"

Esecuzione:

>     Password:auo
>     Password:y22
>     Password:password
>     Password:open sesame
>     Password:unicorn
>     Welcome in

# Capitolo 5. Decisioni

## L'espressione If

Credo sia meglio partire con un esempio a caldo: ecco quindi un programma che calcola il valore assoluto di un numero:

>     n = input("Number? ")
>     if n < 0:
>             print "The absolute value of",n,"is",-n
>     else:
>             print "The absolute value of",n,"is",n

Output di due esecuzioni:

>     Number? -34
>     The absolute value of -34 is 34

>     Number? 1
>     The absolute value of 1 is 1

Quindi cosa fa Python quando esegue questo programma? Prima di tutto chiede all'utente un numero grazie alla linea `'n = input ("Number? ")'` dopodiché legge la linea `'if n < 0':` se `n` è minore di zero Python esegue la linea `'print "The absolute value of ", n, " is ", -n'` altrimenti, cioè se il numero è maggiore di zero, esegue la linea `"print "The absolute value of ", n, "is ", n'`.

Più facilmente Python decide se l'affermazione `n < 0` è vera o falsa. Una espressione `if` è sempre seguita da un blocco di altre espressioni tabulate che vengono eseguite nel caso l'affermazione sia vera. In caso contrario vengono eseguiti i comandi tabulati sotto l'espressione `else`, ovvero quando l'affermazione `if` risulta falsa.

Python presenta svariati operatori associabili al confronto di una variabile: eccone una lista completa:

Tabella 5-1.

Operatore | Funzione
--- | ---
< | minore di
<= | minore o uguale a
> | maggiore di
>= | maggiore o uguale a
== | uguale a
!= | diverso da
<> | diverso da

Un'altra proprietà dell'espressione `if` è la funzione `elif`. `Elif` è un'abbreviazione di `else if` e significa: esegui il blocco di istruzioni tabulato sotto `elif` se la condizione necessaria al primo `if` è falsa e la condizione di `elif` è vera. Ecco un esempio:

>     a = 0
>     while a < 10:
>             a = a + 1
>             if a > 5:
>                     print a," > ",5
>             elif a <= 7:
>                     print a," <= ",7
>             else:
>                     print "Neither test was true"

Output:

>     1  <=  7
>     2  <=  7
>     3  <=  7
>     4  <=  7
>     5  <=  7
>     6  >  5
>     7  >  5
>     8  >  5
>     9  >  5
>     10  >  5

Osservate come la linea `'elif a <= 7:'` entri in azione solamente quando la prima espressione `if` risulta falsa. Come potete vedere l'espressione `elif` permette di fare test multipli all'interno di una singola espressione `if`.

## Esempi

High_low.py

>     #Plays the guessing game higher or lower
>     # (originally written by Josh Cogliati, improved by Quique)

>     #This should actually be something that is semi random like the
>     # last digits of the time or something else, but that will have to
>     # wait till a later chapter.  (Extra Credit, modify it to be random
>     # after the Modules chapter)
>     number = 78
>     guess = 0

>     while guess != number :
>         guess = input ("Guess a number: ")

>         if guess > number :
>             print "Too high"

>         elif guess < number :
>                 print "Too low"

>     print "Just right"

Esecuzione:

>     Guess a number:100
>     Too high
>     Guess a number:50
>     Too low
>     Guess a number:75
>     Too low
>     Guess a number:87
>     Too high
>     Guess a number:81
>     Too high
>     Guess a number:78
>     Just right

even.py

>     #Asks for a number.
>     #Prints if it is even or odd

>     number = input("Tell me a number: ")
>     if number % 2 == 0:
>         print number,"is even."
>     elif number % 2 == 1:
>         print number,"is odd."
>     else:
>         print number,"is very strange."

Esecuzione:

>     Tell me a number: 3
>     3 is odd.

>     Tell me a number: 2
>     2 is even.

>     Tell me a number: 3.14159
>     3.14159 is very strange.

## Esercizi

Scrivete un programma che chieda all'utente di indovinare il vostro nome, ma che dia al giocatore solamente 3 possibilità, fallite le quali il programma terminerà.

Scrivete un programma che chieda all'utente il nome. Se viene inserito il vostro nome il programma dovrà rispondere con un apprezzamento, se il nome inserito è "John Cleese" o "Michel Palin" il programma dovrà rispondere con una battuta mentre in tutti gli altri casi l'output del programma sarà un semplice "Che bel nome!"

# Capitolo 6. Debugging

## Cos'è il Debugging ?

| Poco dopo aver iniziato a programmare ci siamo accorti di come non fosse affatto facile far fare ai programmi quello che volevamo. Avevamo scoperto il Debugging. Posso ricordare il preciso momento in cui ho realizzato che avrei passato buona parte della mia vita a scoprire e correggere gli errori nei miei stessi programmi. |
--Maurice Wilkes scopre il debugging, 1949 |

Se finora avete ripetuto tutti i programmi degli esempi vi sarete certamente accorti che a volte (spesso) il programma da voi scritto assume comportamenti differenti da quelli che avevate previsto. E' molto comune.

Il Debugging è il processo grazie al quale portate il programma a svolgere le funzioni per cui è stato scritto correggendo gli errori e vi assicuro, può essere un'operazione lunga e snervante. Una volta ho impiegato un'intera settimana per correggere un bug dovuto allo scambio di una x con una y...

Questo capitolo sarà più astratto dei precedenti. Vi prego di dirmi se vi è sembrato utile o meno.

## Cosa dovrebbe fare il programma ?

La prima cosa da fare (mi sembra ovvio) è pensare a cosa dovrebbe fare il programma se fosse corretto.

Iniziate ad eseguire qualche test per vedere che cosa succede. Ad esempio, diciamo che ho scritto un programma che calcola il perimetro di un rettangolo (la somma dei quattro lati) e che ho intenzione di testarne il funzionamento immettendo i seguenti casi:

Tabella 6-1.

Larghezza | Altezza | Perimetro
--- | --- | ---
3 | 4 | 14
2 | 3 | 10
4 | 4 | 16
2 | 2 | 8
5 | 1 | 12

Ora avvio il mio programma ed inserirò i dati dei test per vedere se restituisce i risultati che mi aspetto; in caso contrario dovrò scoprire cosa sta facendo il computer.

Comunemente alcuni casi restituiranno il risultato che voglio mentre altri risulteranno sbagliati, quindi dovrete vedere cos'hanno in comune i casi funzionanti. Ecco ad esempio l'output del programma che calcola il perimetro del rettangolo:

>     Height: 3
>     Width: 4
>     perimeter =  15

>     Height: 2
>     Width: 3
>     perimeter =  11

>     Height: 4
>     Width: 4
>     perimeter =  16

>     Height: 2
>     Width: 2
>     perimeter =  8

>     Height: 5
>     Width: 1
>     perimeter =  8

Il programma è scorretto nei primi due casi, corretto nei seguenti due per sbagliare di nuovo nell'ultimo. Provate ad immaginarvi cos'hanno in comune i casi funzionanti. Quando avrete un'idea sul motivo del malfunzionamento trovarne la causa è più facile.

## Cosa fa il programma ?

La prossima cosa da fare è rileggere il codice sorgente. Una delle cose più importanti da fare mentre si programma è leggere e rileggere il codice sorgente. Innanzitutto analizziamo il codice linea per linea comportandoci esattamente come farebbe il programma. Grazie alle strutture di controllo infatti alcune linee di codice possono non essere eseguite mentre altre possono essere eseguite più di una volta. L'importante è che immaginiate ad ogni linea il comportamento di Python.

Iniziamo con il semplice programma per calcolare il perimetro. Non scrivetelo, dovete leggerlo e basta:

>     height = input("Height: ")
>     width = input("Width: ")
>     print "perimeter = ",width+height+width+width

Domanda: Qual'è la prima linea che Python esegue ?

Risposta: `height = input ("Height: ")`.

Domanda: Qual'è il suo effetto ?

Risposta: Stampa `Height:` sullo schermo e attende l'inserimento di un numero da parte dell'utente per metterlo nella variabile `height`.

Domanda: Qual'è la prossima linea che Python esegue ?

Risposta: La linea sotto: `width = input ("Width: ")`.

Domanda: Cosa provoca nel programma ?

Risposta: Stampa `Width:` sullo schermo, attende l'input e assegna il valore immesso alla variabile `width`.

Domanda: Qual'è la prossima linea ?

Risposta: `print "Perimeter = ", width+height+width+width`.

Domanda: ma `width + height + width + width` calcola il perimetro correttamente?

Risposta: Vediamo: il perimetro di un rettangolo si calcola sommando i lati (uh ?). L'ultimo elemento (width) dovrebbe essere un lato (height) non la base (width)...

Domanda: Capisci ora perché alcune volte il perimetro risultava corretto ?

Risposta: Certo, risultava corretto perché tutti i lati erano uguali !!

    . . . .

Ecco il codice:

>     number = 5
>     while number > 1:
>         print ".",
>         number = number - 1
>     print

Questo programma sarà un po' più complesso, come potete notare nel codice è presente una struttura `while`. Bando alle ciance, rimbocchiamoci le maniche e cominciamo.

Domanda: Qual'è la prima linea ad essere eseguita ?

Risposta: La prima linea del file: `'number = 5'`.

Domanda: Cosa fa ?

Risposta: Assegna il valore '5' alla variabile `number`.

Domanda: Come prosegue ?

Risposta: La prossima linea è: `'while number > 1:'`.

Domanda: Cosa fa ?

Risposta: Allora: la struttura `while` verifica che l'espressione che la segue `(number > 1)` sia vera o falsa. Nel primo caso esegue il codice tabulato sotto, nel secondo caso lo salta per passare al codice tabulato al suo stesso livello.

Domanda: Quindi in questo caso come si comporta ?

Risposta: Se la condizione `'number > 1'` è vera eseguirà le due righe di codice successive.

Domanda: La variabile `number` allora è maggiore o minore di 1 ?

Risposta: Il valore di `number` è 5 quindi è maggiore di 1.

Domanda: Quindi qual'è la prossima linea ?

Risposta: La linea indentata appena sotto: `'print ".",'` finché la condizione `while` è vera Python eseguirà questa istruzione, ovvero stamperà un punto e dato che alla fine dell'istruzione compare una virgola, lo stamperà sulla stessa linea del precedente.

Domanda: Ed ora come continua il programma ?

Risposta: `number = number - 1` visto che è indentata sotto il `while`.

Domanda: Cosa fa ?

Risposta: Decrementa la variabile di 1. Quindi number dopo questa istruzione non risulterà più 4 ma 5.

Domanda: Ora come continua ?

Risposta: Dato che il livello di tabulazione decrementa dobbiamo pensare che tipo di struttura di controllo stiamo applicando. Preso atto che è un ciclo `while` dobbiamo tornare alla linea `'while number > 1:'`.

Domanda: Adesso che succede ?

Risposta: Semplice: dopo il riassegnamento della variabile `number`, che è passata da un valore di 5 a un valore di 4, bisogna rifare il confronto tra la condizione del `while` e la variabile.

Domanda: Il risultato qual'è ?

Risposta: La condizione `'number > 1'` è ancora vera quindi il ciclo continua: verranno eseguite per la seconda volta le istruzioni indentate sotto il `while`.

Domanda: Ancora `'print ".",'` e `' number = number - 1'` ?

Risposta: Si :-) Il risultato sarà la stampa di un'altro punto sulla stessa linea del precedente e il decremento di una unità della variabile `number` che assumerà il valore di 3.

Domanda: A questo punto quale sarà la prossima linea ?

Risposta: finché non ci sarà un cambio di indentazione causato dalla fine del ciclo la linea sarà sempre `'while number > 1:'`.

Domanda: Si ricomincia da capo allora ?

Risposta: Già. Verrà aggiunto un'altro punto sulla stessa linea dei precedenti e la variabile `number` verrà decrementata di nuovo. Queste istruzioni verranno eseguite finché la condizione del `while` non risulterà falsa.

Domanda: Riassumendo quindi, alla fine di questo ennesimo ciclo i punti saranno 3 e il valore della variabile `number` sarà 2.

Risposta: Esattamente.

Domanda: Continuiamo? Se non sbaglio ora dobbiamo tornare a `'while number > 1:'`.

Risposta: Si, dobbiamo tornare ancora alla linea che inizia il ciclo `while` per confrontare ancora una volta variabile e condizione del ciclo: dato che 2 è maggiore di 1 eseguiremo ancora le istruzioni indentate sotto. Alla variabile `number` verrà assegnato il valore di 1 e i punti sulla nostra linea diventeranno 4.

Domanda: Aspetta un secondo: i 4 punti sono il risultato finale del programma. Cosa significa ?

Risposta: Significa che probabilmente l'errore è qui :-) Ricominciamo il ciclo: `'while number > 1:'`, ovvero finché la variabile `number` (che ora corrisponde a 1) è maggiore di 1... Ecco l'errore! Il ciclo si interrompe qui visto che 1 non è maggiore di 1.

Domanda: Come posso riparare ?

Risposta: Dato che lo scopo del programma è stampare 5 punti e non 4 dobbiamo semplicemente cambiare la condizione del ciclo `while` sostituendo `'while number > 1:'` con `'while number >= 1:'` Questo non è l'unico modo per eseguire il fix del programma.

## Come riparo il programma ?

Devi capire cosa sta facendo il programma, devi pensare a cosa dovrebbe fare il programma, confrontare e capire la differenza. Il Debugging si impara grazie all'esperienza: se non riuscite a trovare dopo un'ora o due il difetto, fate una pausa e parlatene con qualcuno, quando ci ritornerete sopra avrete nuove idee.

# Capitolo 7. Le funzioni

## Creare funzioni

Inizierò questo capitolo mostrandovi cosa potreste ma non dovreste fare (quindi non scrivete):

>     a = 23
>     b = -23

>     if a < 0:
>         a = -a

>     if b < 0:
>         b = -b

>     if a == b:
>         print "The absolute values of", a,"and",b,"are equal"
>     else:
>         print "The absolute values of a and b are different"

L'output sarebbe:

>     The absolute values of 23 and 23 are equal

Il programma sembra un po' ripetitivo (e i programmatori odiano ripetere le cose, i computer servono a quello no ??). Fortunatamente Python permette di creare funzioni per rimuovere i duplicati. Ecco l'esempio riscritto:

>     a = 23
>     b = -23

>     def my_abs(num):
>         if num < 0:
>             num = -num
>         return num

>     if my_abs(a) == my_abs(b):
>         print "The absolute values of", a,"and",b,"are equal"
>     else:
>         print "The absolute values of a and b are different"

l'output è:

>     The absolute values of 23 and -23 are equal

L'elemento chiave di questo programma è l'istruzione `def. def` (abbreviazione di define, definisci) inizializza la definizione di una funzione. `def` è seguita dal nome della funzione `abs`. Poi troviamo una "(" seguita dal parametro `num` (che viene passato dal programma ad ogni chiamata di funzione). Le istruzioni dopo il ":" vengono eseguite ogni volta che la funzione viene usata dal programma e si possono distinguere dalle normali righe di codice perché sono indentate sotto la funzione. Essa, infatti, finisce quando la tabulazione torna al suo livello o quando incontra `return`. L'istruzione `return` ritorna un valore dove è stata chiamata la funzione.

Osservate che i valori `a` e `b` non sono cambiati. Le funzioni ovviamente possono essere usate anche per ripetere azioni che non ritornano alcun valore.

Ecco qualche esempio:

>     def hello():
>         print "Hello"

>     def area(width,height):
>         return width*height

>     def print_welcome(name):
>         print "Welcome",name

>     hello()
>     hello()

>     print_welcome("Fred")
>     w = 4
>     h = 5
>     print "width =",w,"height =",h,"area =",area(w,h)

L'output è:

>     Hello
>     Hello
>     Welcome Fred
>     width = 4 height = 5 area = 20

Questo esempio mostra solamente un po' più in profondità in quanti differenti modi si possono applicare le funzioni. Osservate attentamente, potete anche non dare argomenti ad una funzione così come potete dargliene più d'uno. Osservate anche che `return` è opzionale.

Le funzioni possono essere usate per eliminare le ripetizioni di codice.

## Esempi

factorial.py

>     #defines a function that calculates the factorial

>     def factorial(n):
>         if n <= 1:
>             return 1
>         return n*factorial(n-1)

>     print "2! = ",factorial(2)
>     print "3! = ",factorial(3)
>     print "4! = ",factorial(4)
>     print "5! = ",factorial(5)

Output:

>     2! =  2
>     3! =  6
>     4! =  24
>     5! =  120

temperature2.py

>     #converts temperature to fahrenheit or celsius

>     def print_options():
>         print "Options:"
>         print " 'p' print options"
>         print " 'c' convert from celsius"
>         print " 'f' convert from fahrenheit"
>         print " 'q' quit the program"

>     def celsius_to_fahrenheit(c_temp):
>         return 9.0/5.0*c_temp+32

>     def fahrenheit_to_celsius(f_temp):
>         return (f_temp - 32.0)*5.0/9.0

>     choice = "p"
>     while choice != "q":
>         if choice == "c":
>             temp = input("Celsius temperature:")
>             print "Fahrenheit:",celsius_to_fahrenheit(temp)
>         elif choice == "f":
>             temp = input("Fahrenheit temperature:")
>             print "Celsius:",fahrenheit_to_celsius(temp)
>         elif choice != "q":
>             print_options()
>         choice = raw_input("option:")

Esecuzione:

>     > python temperature2.py
>     Options:
>      'p' print options
>      'c' convert from celsius
>      'f' convert from fahrenheit
>      'q' quit the program
>     option:c
>     Celsius temperature:30
>     Fahrenheit: 86.0
>     option:f
>     Fahrenheit temperature:60
>     Celsius: 15.5555555556
>     option:q

area2.py

>     #By Amos Satterlee
>     print
>     def hello():
>         print 'Hello!'

>     def area(width,height):
>         return width*height

>     def print_welcome(name):
>         print 'Welcome,',name

>     name = raw_input('Your Name: ')
>     hello(),
>     print_welcome(name)
>     print
>     print 'To find the area of a rectangle,'
>     print 'Enter the width and height below.'
>     print
>     w = input('Width:  ')
>     while w <= 0:
>         print 'Must be a positive number'
>         w = input('Width:  ')
>     h = input('Height: ')
>     while h <= 0:
>         print 'Must be a positive number'
>         h = input('Height: ')
>     print 'Width =',w,' Height =',h,' so Area =',area(w,h)

Esecuzione:

>     Your Name: Josh
>     Hello!
>     Welcome, Josh

>     To find the area of a rectangle,
>     Enter the width and height below.

>     Width:  -4
>     Must be a positive number
>     Width:  4
>     Height: 3
>     Width = 4  Height = 3  so Area = 12

## Esercizi

Riscrivete il programma area.py della sezione 3.2 definendo funzioni separate per l'area del quadrato, del rettangolo e del cerchio (3.14 * raggio**2). Create anche un'interfaccia a menu.

# Capitolo 8. Liste

## Variabili con più di un valore

Avete già visto le variabili ordinarie che immagazzinano un singolo valore. Tuttavia esistono altri tipi di variabili che possono contenere più di un valore: queste variabili vengono chiamate liste. Ecco un esempio del'utilizzo delle liste:

>     which_one = input("What month (1-12)? ")
>     months = ['January', 'February', 'March', 'April', 'May', 'June', 'July',\
>             'August', 'September', 'October', 'November', 'December']
>     if 1 <= which_one <= 12:
>             print "The month is",months[which_one - 1]

L'output sarà questo:

>     What month (1-12)? 3
>     The month is March

In questo esempio la variabile `months` è una `lista`. `months` è definita dalla linea `months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]` (osserva nel codice che \ permette di andare a capo quando la linea di codice è troppo lunga). Le parentesi quadrate "[" e "]" iniziano e finiscono la lista e la virgola separa un elemento della lista dall'altro. La lista qui descritta viene usata nell'istruzione `months [which_one - 1]` e consiste in un insieme di elementi numerati partendo da 0. In altre parole se volete l'elemento `'January'` della lista `months` dovete usare `months [0]`. Ovvero quando assegnate a una lista un numero utilizzando la sintassi appena descritta essa ritornerà l'elemento immagazzinato nella locazione corrispondente.

L'istruzione `'if 1 <= wich_month <= 12:'` sarà vera solo nel caso in cui `which_one` sia un numero tra 1 e 12 inclusi.

Le liste possono essere pensate come una serie di scatole. Ad esempio le scatole create da `demolist = ['life', 42, 'the universe', 6, 'and', 7]` sarebbero all'incirca così:

Tabella 8-1.

box number | 0 | 1 | 2 | 3 | 4 | 5
--- | --- | --- | --- | --- | --- | ---
demolist | `life' | 42 | `the universe' | 6 | `and' | 7

Ogni scatola ha un numero di riferimento cosicchè l'istruzione `demolist [0]` seleziona l'elemento `'life'` dalla lista, `demolist [1]` l'elemento 42, `demolist[5]` l'elemento 7.

## Altre funzioni delle liste

Il prossimo esempio vi mostrerà moltissimi altri utilizzi per le liste (non mi aspetto che proviate ogni esempio, ma dovreste provarli finché non vi sentite a vostro agio nell'utilizzo delle liste). Iniziamo:

>     demolist = ['life',42, 'the universe', 6,'and',7]
>     print 'demolist = ',demolist
>     demolist.append('everything')
>     print "after 'everything' was appended demolist is now:"
>     print demolist
>     print 'len(demolist) =', len(demolist)
>     print 'demolist.index(42) =',demolist.index(42)
>     print 'demolist[1] =', demolist[1]
>     #Next we will loop through the list
>     c = 0
>     while c < len(demolist):
>         print 'demolist[',c,']=',demolist[c]
>         c = c + 1
>     del demolist[2]
>     print "After 'the universe' was removed demolist is now:"
>     print demolist
>     if 'life' in demolist:
>         print "'life' was found in demolist"
>     else:
>         print "'life' was not found in demolist"
>     if 'amoeba' in demolist:
>         print "'amoeba' was found in demolist"
>     if 'amoeba' not in demolist:
>         print "'amoeba' was not found in demolist"
>     demolist.sort()
>     print 'The sorted demolist is ',demolist

E questo è l'output:

>     demolist =  ['life', 42, 'the universe', 6, 'and', 7]
>     after 'everything' was appended demolist is now:
>     ['life', 42, 'the universe', 6, 'and', 7, 'everything']
>     len(demolist) = 7
>     demolist.index(42) = 1
>     demolist[1] = 42
>     demolist[ 0 ]= life
>     demolist[ 1 ]= 42
>     demolist[ 2 ]= the universe
>     demolist[ 3 ]= 6
>     demolist[ 4 ]= and
>     demolist[ 5 ]= 7
>     demolist[ 6 ]= everything
>     After 'the universe' was removed demolist is now:
>     ['life', 42, 6, 'and', 7, 'everything']
>     'life' was found in demolist
>     'amoeba' was not found in demolist
>     The sorted demolist is  [6, 7, 42, 'and', 'everything', 'life']

Questo esempio utilizza moltissime nuove funzioni. Ad esempio guardate come potete stampare un'intera lista per poi aggiungere nuovi elementi con la funzione `append`. `len` serve a contare quanti elementi sono presenti nella lista: le entrate (index) valide di una lista (cioè quelle richiamabili grazie a `nome_lista` [numero dell'elemento]) vanno da 0 a `len - 1`. La funzione `index` serve a sapere la posizione di un elemento in una lista: nel caso esistano elementi con lo stesso nome ritornerà la prima posizione dell'elemento. Osservate come l'istruzione `demolist.index (42)` ritorni il valore 1 e l'istruzione `demolist [1]` ritorni il valore 42. La linea `#Next we will loop through the list` è un semplice commento usato per introdurre le prossime righe di codice:

>     c = 0
>     while c < len(demolist):
>         print 'demolist[',c,']=',demolist[c]
>         c = c + 1

crea una variabile `c` inizialmente di valore 0 che viene incrementata finché non raggiunge l'ultimo elemento della lista. Nel frattempo l'istruzione `print` stampa ogni elemento della lista.

L'istruzione `del` può essere usata per rimuovere un elemento dalla lista. Le linee successive utilizzano l'operatore `index` per sapere se un elemento è presente o meno nella lista.

La funzione `sort` ordina la lista ed è utile se avete bisogno di una lista ordinata dall'elemento più piccolo a quello più grande oppure in ordine alfabetico.

Riassumendo possiamo compiere le seguenti operazioni:

Tabella 8-2.

esempio | spiegazione
--- | ---
`list[2]` | accesso all'elemento 2 dell'indice
`list[2] = 3` | imposta a 3 l'elemento 2 dell'indice
`del list[2]` | cancella l'elemento 2 dell'indice
`len(list)` | restituisci la lunghezza della lista
`"value" in list` | è vero se "value" è un elemento della lista
`"value" not in list` | è vero se "value" non è un elemento della lista
`list.sort()` | ordina la lista
`list.index("value")` | restituisce l'indice dove viene trovata la prima occorrenza di "value"
`list.append("value")` | aggiunge l'elemento "value" alla fine della lista

Il prossimo esempio applica queste funzioni per qualcosa di più utile:

>     menu_item = 0
>     list = []
>     while menu_item != 9:
>             print "--------------------"
>             print "1. Print the list"
>             print "2. Add a name to the list"
>             print "3. Remove a name from the list"
>             print "4. Change an item in the list"
>             print "9. Quit"
>             menu_item = input("Pick an item from the menu: ")
>             if menu_item == 1:
>                     current = 0
>                     if len(list) > 0:
>                             while current < len(list):
>                                     print current,". ",list[current]
>                                     current = current + 1
>                     else:
>                             print "List is empty"
>             elif menu_item == 2:
>                     name = raw_input("Type in a name to add: ")
>                     list.append(name)
>             elif menu_item == 3:
>                     del_name = raw_input("What name would you like to remove: ")
>                     if del_name in list:
>                             item_number = list.index(del_name)
>                             del list[item_number]
>                     else:
>                             print del_name," was not found"
>             elif menu_item == 4:
>                     old_name = raw_input("What name would you like to change: ")
>                     if old_name in list:
>                             item_number = list.index(old_name)
>                             new_name = raw_input("What is the new name: ")
>                             list[item_number] = new_name
>                     else:
>                             print old_name," was not found"
>     print "Goodbye"

Ecco una parte dell'output:

>     --------------------
>     1. Print the list
>     2. Add a name to the list
>     3. Remove a name from the list
>     4. Change an item in the list
>     9. Quit

>     Pick an item from the menu: 2
>     Type in a name to add: Jack

>     Pick an item from the menu: 2
>     Type in a name to add: Jill

>     Pick an item from the menu: 1
>     0 .  Jack
>     1 .  Jill

>     Pick an item from the menu: 3
>     What name would you like to remove: Jack

>     Pick an item from the menu: 4
>     What name would you like to change: Jill
>     What is the new name: Jill Peters

>     Pick an item from the menu: 1
>     0 .  Jill Peters

>     Pick an item from the menu: 9
>     Goodbye

E' un programma abbastanza lungo, diamo un'occhiata al codice sorgente per capirlo meglio. La linea `list = []` crea una variabile `list` senza elementi al suo interno. La prossima linea importante è `while menu_item != 9:` . Questa linea inizia un ciclo che permette di ottenere il menu di questo programma. Le linee seguenti del programma visualizzano un menu per decidere quale parte del programma eseguire.

La sezione:

>     current = 0
>     if len(list) > 0:
>             while current < len(list):
>                     print current,". ",list[current]
>                     current = current + 1
>     else:
>             print "List is empty"

Scorre tutta la lista e visualizza ogni suo elemento. `len(list)` conta quanti elementi sono presenti nella lista, se ritorna 0 la lista è vuota.

Poche linee più sotto appare l'istruzione `list.append(name)` che aggiunge un elemento alla fine della lista. Saltate giù di un'altro paio di linee e osservate questa sezione di codice:

>     item_number = list.index(del_name)
>     del list[item_number]

Qui la funzione `index` viene utilizzata per trovare l'indice dell'elemento richiesto per poi utilizzarlo nella sua cancellazione. `del list [item_number]` viene utilizzato appunto per rimuovere l'elemento.

La prossima sezione:

>     old_name = raw_input("What name would you like to change: ")
>     if old_name in list:
>             item_number = list.index(old_name)
>             new_name = raw_input("What is the new name: ")
>             list[item_number] = new_name
>     else:
>             print old_name," was not found"

Usa index per trovare l'elemento da modificare e sostituire il vecchio valore `(old_name)` con il nuovo valore desiderato `(new_name)`.

## Esempi

test.py

>     ## This program runs a test of knowledge

>     true = 1
>     false = 0

>     # First get the test questions
>     # Later this will be modified to use file io.
>     def get_questions():
>         # notice how the data is stored as a list of lists
>         return [["What color is the daytime sky on a clear day?","blue"],\
>                 ["What is the answer to life, the universe and everything?","42"],\
>                 ["What is a three letter word for mouse trap?","cat"]]

>     # This will test a single question
>     # it takes a single question in
>     # it returns true if the user typed the correct answer, otherwise false
>     def check_question(question_and_answer):
>         #extract the question and the answer from the list
>         question = question_and_answer[0]
>         answer = question_and_answer[1]
>         # give the question to the user
>         given_answer = raw_input(question)
>         # compare the user's answer to the testers answer
>         if answer == given_answer:
>             print "Correct"
>             return true
>         else:
>             print "Incorrect, correct was:",answer
>             return false

>     # This will run through all the questions
>     def run_test(questions):
>         if len(questions) == 0:
>             print "No questions were given."
>             # the return exits the function
>             return
>         index = 0
>         right = 0
>         while index < len(questions):
>             #Check the question
>             if check_question(questions[index]):
>                 right = right + 1
>             #go to the next question
>             index = index + 1
>         #notice the order of the computation, first multiply, then divide
>         print "You got ",right*100/len(questions),"% right out of",len(questions)

>     #now lets run the questions
>     run_test(get_questions())

Output:

>     What color is the daytime sky on a clear day?green
>     Incorrect, correct was: blue
>     What is the answer to life, the universe and everything?42
>     Correct
>     What is a three letter word for mouse trap?cat
>     Correct
>     You got  66 % right out of 3

## Esercizi

Espandete il programma test.py in modo che abbia un menu per selezionare le opzioni del test, la lista delle domande e un'opzione per terminare l'esecuzione. Aggiungete inoltre un'altra domanda: "What noise does a truly advanced machine make ?" la risposta sarà "Ping".

# Capitolo 9. Cicli For

Niente paragrafi, partiamo subito con un esercizio che ovviamente dovete provare sui vostri computer :=) :

>     onetoten = range(1,11)
>     for count in onetoten:
>             print count

L'onnipresente output:

>     1
>     2
>     3
>     4
>     5
>     6
>     7
>     8
>     9
>     10

L'output è familiare ma il codice è diverso. La prima linea utilizza la funzione `range` che richiede due argomenti, proprio come nell'esempio: `range (inizio, fine)`. inizio è il primo numero che viene prodotto mentre fine è maggiore di 1 dell'ultimo numero prodotto. Questo programma avrebbe anche potuto essere scritto più brevemente:

>     for count in range(1,11):
>             print count

Ecco a voi alcuni esempi per capire meglio il funzionamento di `range`:

>     >>> range(1,10)
>     [1, 2, 3, 4, 5, 6, 7, 8, 9]
>     >>> range(-32, -20)
>     [-32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21]
>     >>> range(5,21)
>     [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
>     >>> range(21,5)
>     []

Avrete certamente notato la presenza di una nuova struttura di controllo, gli esempi infatti usano la struttura `for`. La sintassi del controllo `for` è: `for variabile nella lista:`. La lista viene quindi attraversata dal primo elemento all'ultimo e mentre il ciclo `for` compie il suo tragitto ogni elemento viene inserito in una variabile.

Ecco un'altra dimostrazione:

>     demolist = ['life',42, 'the universe', 6,'and',7,'everything']
>     for item in demolist:
>         print "The Current item is:",
>         print item

Output:

>     The output is:
>     The Current item is: life
>     The Current item is: 42
>     The Current item is: the universe
>     The Current item is: 6
>     The Current item is: and
>     The Current item is: 7
>     The Current item is: everything

Osservate come il ciclo `for` scorra tutti gli elementi nella lista. (Provate ad esempio a togliere la virgola alla fine dell'istruzione `print` o a cambiare il testo all'interno della stessa... smanettateci un po' insomma :=) ). Quindi, a cosa serve? Beh, serve a scorrere uno ad uno tutti gli elementi di una lista e a fare qualcosa con ognuno di essi. Per esempio potete sommare tutti gli elementi:

>     list = [2,4,6,8]
>     sum = 0
>     for num in list:
>             sum = sum + num
>     print "The sum is: ",sum

L'output sarà semplicemente:

>     The sum is: 20

Altrimenti potreste scrivere un semplice programma per trovare i duplicati in una lista. Ad esempio:

>     list = [4, 5, 7, 8, 9, 1,0,7,10]
>     list.sort()
>     prev = list[0]
>     del list[0]
>     for item in list:
>             if prev == item:
>                     print "Duplicate of ",prev," Found"
>             prev = item

Il cui output è ovviamente:

>     Duplicate of 7 found

Va bene, allora come funziona? Scriviamo il programma in modo che ritorni un risultato passaggio per passaggio, qualcosa di molto simile al debugging:

>     l = [4, 5, 7, 8, 9, 1,0,7,10]
>     print "l = [4, 5, 7, 8, 9, 1,0,7,10]","\tl:",l
>     l.sort()
>     print "l.sort()","\tl:",l
>     prev = l[0]
>     print "prev = l[0]","\tprev:",prev
>     del l[0]
>     print "del l[0]","\tl:",l
>     for item in l:
>             if prev == item:
>                     print "Duplicate of ",prev," Found"
>             print "if prev == item:","\tprev:",prev,"\titem:",item
>             prev = item
>             print "prev = item","\t\tprev:",prev,"\titem:",item

l'output è cambiato:

>     l = [4, 5, 7, 8, 9, 1,0,7,10]   l: [4, 5, 7, 8, 9, 1, 0, 7, 10]
>     l.sort()        l: [0, 1, 4, 5, 7, 7, 8, 9, 10]
>     prev = l[0]     prev: 0
>     del l[0]        l: [1, 4, 5, 7, 7, 8, 9, 10]
>     if prev == item:        prev: 0         item: 1
>     prev = item             prev: 1         item: 1
>     if prev == item:        prev: 1         item: 4
>     prev = item             prev: 4         item: 4
>     if prev == item:        prev: 4         item: 5
>     prev = item             prev: 5         item: 5
>     if prev == item:        prev: 5         item: 7
>     prev = item             prev: 7         item: 7
>     Duplicate of  7  Found
>     if prev == item:        prev: 7         item: 7
>     prev = item             prev: 7         item: 7
>     if prev == item:        prev: 7         item: 8
>     prev = item             prev: 8         item: 8
>     if prev == item:        prev: 8         item: 9
>     prev = item             prev: 9         item: 9
>     if prev == item:        prev: 9         item: 10
>     prev = item             prev: 10        item: 10

La ragione per cui ho inserito così tanti `print` nel codice è che in questo modo riuscite a vedere il comportamento del programma linea per linea (quindi se non riuscite ad immaginare il problema di un programma malfunzionante tentate di mettere molti `print` per individuarlo con più facilità).

Il programma inizia con la nostra solita noiosa e vecchia lista che ordina nella seconda linea a seconda del valore degli elementi (dal minore al maggiore) in modo che ogni duplicato, se ce ne sono, sia vicino all'"originale". Dopo questi primi passi viene inizializzata una variabile `prev(ious)`. Il primo elemento della `lista (0)` viene cancellato perché altrimenti sarebbe incorrettamente sembrato un duplicato della variabile `prev`. La linea successiva, come potete vedere, è un ciclo `for`. Ogni singolo elemento della lista viene in questo modo testato e confrontato con il precedente per riconoscere eventuali duplicati. Questo avviene memorizzando il valore del precedente elemento della lista nella variabile `prev` e confrontando quest'ultima con l'elemento corrente. `prev` viene quindi di volta in volta (ad ogni ciclo) riassegnato in modo che l'elemento corrente venga sempre confrontato con quello appena precedente nella lista.

Osservate anche come viene utilizzato /t per stampare una tabulazione.

Un'altro modo per utilizzare un ciclo `for` è ripetere la stessa azione un deterninato numero di volte. Ecco il codice per visualizzare i primi 11 numeri della serie di Fibonacci:

>     a = 1
>     b = 1
>     for c in range(1,10):
>             print a,
>             n = a + b
>             a = b
>             b = n

con il sorprendente output:

1 1 2 3 5 8 13 21 34

Tutto quello che potete fare con i cicli `for` potete farlo anche con `while` ma grazie ai cicli `for` è più semplice scorrere tra tutti gli elementi di una lista o compiere un'azione un determinato numero di volte.

# Capitolo 10. Espressioni Booleane

Ecco un piccolo esempio di espressioni booleane (non dovete scriverli):

>     a = 6
>     b = 7
>     c = 42
>     print 1, a == 6
>     print 2, a == 7
>     print 3,a == 6 and b == 7
>     print 4,a == 7 and b == 7
>     print 5,not a == 7 and b == 7
>     print 6,a == 7 or b == 7
>     print 7,a == 7 or b == 6
>     print 8,not (a == 7 and b == 6)
>     print 9,not a == 7 and b == 6

Questo l'immancabile output:

>     1 1
>     2 0
>     3 1
>     4 0
>     5 1
>     6 1
>     7 0
>     8 1
>     9 0

Cosa succede ? Il programma consiste in una serie di istruzioni `print`; ogni istruzione `print` visualizza un numero e un'espressione. Il numero serve a farvi capire quale istruzione viene eseguita. Potete notare che ogni espressione consiste in uno 0 o in un 1: in Python equivalgono a falso (0) e a vero(1). Le linee:

>     print 1, a == 6
>     print 2, a == 7

restituiscono infatti vero e falso, esattamente come dovrebbero fare finché la prima affermazione è vera e la seconda è falsa. La terza istruzione `print` è un po' diversa: `print 3, a == 6 and b == 7`. L'operatore `and` significa se entrambe le affermazioni prima e dopo l'operatore logico `and` sono vere tutta l'espressione è vera altrimenti tutta l'espressione è falsa. L'espressione successiva, `print 4, a == 7 and b == 7`, dimostra che se una parte dell'espressione `and` è falsa tutta l'espressione sarà falsa. Il significato di `and` può essere riassunto come segue:

Tabella 10-1.

espressione | risultato
--- | ---
vero`and` vero | vero
vero`and` falso | falso
falso`and` vero | falso
falso`and` falso | falso

Potete notare che se la prima espressione è falsa Python non esegue un check sulla seconda espressione perché sa già che tutta l'espressione è falsa.

La linea successiva, `print 5, not a == 7 and b == 7`, utilizza l'operatore `not` che restituisce semplicemente l'opposto dell'espressione.

L'espressione può infatti essere riscritta semplicemente come `print 5, a != 7 and b == 7`. Questa è la tabella:

Tabella 10-2.

espressione | risultato
--- | ---
`not` vero | falso
`not` falso | vero

Le due linee seguenti, `print 6, a == 7 or b == 7` e `print 7, a == 7 or b == 6`, utilizzano l'operatore logico `or` che ritorna vero se una delle affermazioni (o entrambe) è vera.

Tabella 10-3.

espressione | risultato
--- | ---
vero`or` vero | vero
vero`or` falso | vero
falso`or` vero | vero
falso`or` falso | falso

Anche qui Python non esegue il check sulla seconda espressione se riconosce la prima come vera dato che anche se la seconda affermazione risultasse falsa l'intera espressione sarebbe comunque vera.

Le ultime due linee, `print 8, not (a == 7 and b == 6)` e `print 9, not a == 7 and b == 6`, mostrano come le parentesi possano raggruppare espressioni e forzarne l'esecuzione prima di altre al di fuori dalle parentesi. Potete osservare infatti che le parentesi cambiano il valore dell'espressione da falso a vero, visto che obbligano l'operatore `not` a valutare l'intera espressione anziché solamente `a == 7`.

Ecco un esempio dell'utilizzo delle espressioni booleane:

>     list = ["Life","The Universe","Everything","Jack","Jill","Life","Jill"]

>     #make a copy of the list
>     copy = list[:]
>     #sort the copy
>     copy.sort()
>     prev = copy[0]
>     del copy[0]

>     count = 0

>     #go through the list searching for a match
>     while count < len(copy) and copy[count] != prev:
>         prev = copy[count]
>         count = count + 1

>     #If a match was not found then count can't be < len
>     #since the while loop continues while count is < len
>     #and no match is found
>     if count < len(copy):
>         print "First Match: ",prev

Ecco l'output:

>     First Match:  Jill

Questo programma continua a scorrere la lista cercando duplicati `while count < (len (copy) and copy [count])`. Quando uno dei due contatori è più grande dell'ultimo indice di `copy` o viene trovato un duplicato, l'operatore `and` non risulta più vero e si esce dal ciclo. `if` si occupa semplicemente di accertarsi che l'uscita dal ciclo sia dovuta alla presenza di un duplicato.

Nell'esempio viene utilizzato un'altro 'trucco' dell'operatore `and`. Se guardate la tabella di `and` potete osservare che la terza espressione è falsa senza che Python esegua un check sul secondo elemento. Se `count >= len (copy)` (in altre parole `count < len (copy)` è falsa) allora `copy[count]` non viene processata. Questo avviene perché Python sa che se la prima accezione è falsa, lo sono entrambe. Questo piccolo trucco è utile se la seconda metà dell'`and` causa un errore. Ho usato la prima espressione `(count < len(copy))` per eseguire un check su `count` e controllare se `count` sia un indice valido. (Se non mi credete, rimuovete 'Jill' e 'Life', eseguite il programma e vedete se funziona ancora, quindi invertite l'ordine di `count < len(copy) and copy[count] != prev con copy[count] != prev and count < len(copy))`.

Le espressioni booleane possono essere usate quando avete bisogno di verificare due o più elementi in una volta.

## Esempi

password1.py

>     ## Questo programma chiede all'utente uno username e una password
>     #  dopodiché verifica se l'utente è autenticato

>     name = raw_input("What is your name? ")
>     password = raw_input("What is the password? ")
>     if name == "Josh" and password == "Friday":
>         print "Welcome Josh"
>     elif name == "Fred" and password == "Rock":
>         print "Welcome Fred"
>     else:
>         print "I don't know you."

Semplice esecuzione:

>     What is your name? Josh
>     What is the password? Friday
>     Welcome Josh

>     What is your name? Bill
>     What is the password? Money
>     I don't know you.

## Esercizi

Scrivete un programma che spinga l'utente ad indovinare il vostro nome dandogli solamente 3 possibilità, dopo le quali il programma termina.

# Capitolo 11. Dizionari

Questo capitolo tratta i dizionari. I dizionari hanno chiavi e valori: le chiavi sono usate per trovare i valori. Ecco un esempio di un dizionario in uso:

>     def print_menu():
>         print '1. Print Phone Numbers'
>         print '2. Add a Phone Number'
>         print '3. Remove a Phone Number'
>         print '4. Lookup a Phone Number'
>         print '5. Quit'
>         print
>     numbers = {}
>     menu_choice = 0
>     print_menu()
>     while menu_choice != 5:
>         menu_choice = input("Type in a number (1-5):")
>         if menu_choice == 1:
>             print "Telephone Numbers:"
>             for x in numbers.keys():
>                 print "Name: ",x," \tNumber: ",numbers[x]
>             print
>         elif menu_choice == 2:
>             print "Add Name and Number"
>             name = raw_input("Name:")
>             phone = raw_input("Number:")
>             numbers[name] = phone
>         elif menu_choice == 3:
>             print "Remove Name and Number"
>             name = raw_input("Name:")
>             if numbers.has_key(name):
>                 del numbers[name]
>             else:
>                 print name," was not found"
>         elif menu_choice == 4:
>             print "Lookup Number"
>             name = raw_input("Name:")
>             if numbers.has_key(name):
>                 print "The number is",numbers[name]
>             else:
>                 print name," was not found"
>         elif menu_choice != 5:
>             print_menu()

Ecco l'output:

>     1. Print Phone Numbers
>     2. Add a Phone Number
>     3. Remove a Phone Number
>     4. Lookup a Phone Number
>     5. Quit

>     Type in a number (1-5):2
>     Add Name and Number
>     Name:Joe
>     Number:545-4464
>     Type in a number (1-5):2
>     Add Name and Number
>     Name:Jill
>     Number:979-4654
>     Type in a number (1-5):2
>     Add Name and Number
>     Name:Fred
>     Number:132-9874
>     Type in a number (1-5):1
>     Telephone Numbers:
>     Name:  Fred     Number:  132-9874
>     Name:  Joe      Number:  545-4464
>     Name:  Jill     Number:  979-4654

>     Type in a number (1-5):4
>     Lookup Number
>     Name:Joe
>     The number is 545-4464
>     Type in a number (1-5):3
>     Remove Name and Number
>     Name:Fred
>     Type in a number (1-5):1
>     Telephone Numbers:
>     Name:  Joe      Number:  545-4464
>     Name:  Jill     Number:  979-4654

>     Type in a number (1-5):5

Questo programma è simile a quello con la lista di nomi nel capitolo sulle liste. Ecco come funziona il programma. Innanzitutto viene definita la funzione `print_menu` che visualizza sullo schermo un menu più volte usato nel programma. A questo punto compare la linea `numbers = {}` che dichiara `numbers` come un dizionario. Le linee seguenti fanno funzionare il menu:

>     for x in numbers.keys():
>         print "Name: ",x," \tNumber: ",numbers[x]

Grazie a questo ciclo si possono visualizzare le informazioni contenute nel dizionario. La funzione `number.keys()` restituisce una lista che viene poi utilizzata dal ciclo `for`. Questa lista non è in nessun ordine particolare quindi se la volete in ordine alfabetico essa deve essere ordinata. Con la notazione `numbers[x]` possiamo accedere ai singoli membri del dizionario: ovviamente in questo caso `x` è una stringa. Successivamente la linea `numbers[name] = phone` aggiunge un nome e un numero di telefono al dizionario. Se `name` è stato già inserito nel dizionario `phone`, rimpiazza il valore precedente. Le linee:

>     if numbers.has_key(name):
>         del numbers[name]

Controllano se una chiave è già presente nel dizionario, in tal caso la rimuovono. La funzione `numbers.has_key(name)` ritorna vero se `name` è presente in `numbers` altrimenti ritorna falso. La linea `del numbers[name]` rimuove la chiave `[name]` e il valore ad essa associato. Le linee:

>     if numbers.has_key(name):
>         print "The number is",numbers[name]

Controllano se nel dizionario è presente una determinata chiave, se la trovano, stampano il numero ad essa associato. Infine se la scelta non è presente nel menu (quindi non è valida) il programma rivisualizza il menu.

Ricapitolando: i dizionari hanno chiavi e valori. Le chiavi possono essere stringhe o numeri e puntano a valori. I valori puntati possono essere qualsiasi tipo di variabile, anche liste di dizionari (i quali possono contenere a loro volta dizionari e liste (paura eh? :=) )). Questo è un esempio che utilizza una lista in un dizionario:

>     max_points = [25,25,50,25,100]
>     assignments = ['hw ch 1','hw ch 2','quiz   ','hw ch 3','test']
>     students = {'#Max':max_points}

>     def print_menu():
>         print "1. Add student"
>         print "2. Remove student"
>         print "3. Print grades"
>         print "4. Record grade"
>         print "5. Print Menu"
>         print "6. Exit"

>     def print_all_grades():
>             print '\t',
>             for i in range(len(assignments)):
>                 print assignments[i],'\t',
>             print
>             keys = students.keys()
>             keys.sort()
>             for x in keys:
>                 print x,'\t',
>                 grades = students[x]
>                 print_grades(grades)

>     def print_grades(grades):
>         for i in range(len(grades)):
>             print grades[i],'\t\t',
>         print

>     print_menu()
>     menu_choice = 0
>     while menu_choice != 6:
>         print
>         menu_choice = input("Menu Choice (1-6):")
>         if menu_choice == 1:
>             name = raw_input("Student to add:")
>             students[name] = [0]*len(max_points)
>         elif menu_choice == 2:
>             name = raw_input("Student to remove:")
>             if students.has_key(name):
>                 del students[name]
>             else:
>                 print "Student: ",name," not found"
>         elif menu_choice == 3:
>             print_all_grades()

>         elif menu_choice == 4:
>             print "Record Grade"
>             name = raw_input("Student:")
>             if students.has_key(name):
>                 grades = students[name]
>                 print "Type in the number of the grade to record"
>                 print "Type a 0 (zero) to exit"
>                 for i in range(len(assignments)):
>                     print i+1,' ',assignments[i],'\t',
>                 print
>                 print_grades(grades)
>                 which = 1234
>                 while which != -1:
>                     which = input("Change which Grade:")
>                     which = which-1
>                     if 0 <= which < len(grades):
>                         grade = input("Grade:")
>                         grades[which] = grade
>                     elif which != -1:
>                         print "Invalid Grade Number"
>             else:
>                 print "Student not found"
>         elif menu_choice != 6:
>             print_menu()

E questo è l'output:

>     1. Add student
>     2. Remove student
>     3. Print grades
>     4. Record grade
>     5. Print Menu
>     6. Exit

>     Menu Choice (1-6):3
>             hw ch 1         hw ch 2         quiz            hw ch 3         test
>     #Max    25              25              50              25              100

>     Menu Choice (1-6):1
>     1. Add student
>     2. Remove student
>     3. Print grades
>     4. Record grade
>     5. Print Menu
>     6. Exit

>     Menu Choice (1-6):1
>     Student to add:Bill

>     Menu Choice (1-6):4
>     Record Grade
>     Student:Bill
>     Type in the number of the grade to record
>     Type a 0 (zero) to exit
>     1   hw ch 1     2   hw ch 2     3   quiz        4   hw ch 3     5   test
>     0               0               0               0               0
>     Change which Grade:1
>     Grade:25
>     Change which Grade:2
>     Grade:24
>     Change which Grade:3
>     Grade:45
>     Change which Grade:4
>     Grade:23
>     Change which Grade:5
>     Grade:95
>     Change which Grade:0

>     Menu Choice (1-6):3
>             hw ch 1         hw ch 2         quiz            hw ch 3         test
>     #Max    25              25              50              25              100
>     Bill    25              24              45              23              95

>     Menu Choice (1-6):6

La variabile `students` è un dizionario le cui chiavi sono i nomi degli studenti e i valori, i voti degli studenti. Le prime due linee creano semplicemente due liste. La linea successiva `students = {'#Max':max_points}` crea un nuovo dizionario la cui chiave è `#Max` e il valore [25,25,50,25,100] (è il valore di `max_points` nel momento in cui il valore viene assegnato; viene usata la chiave `#Max` perché " # " è sempre ordinato sopra i caratteri alfabetici). Quindi viene definita la funzione `print_menu`. Le linee:

>     def print_all_grades():
>             print '\t',
>             for i in range(len(assignments)):
>                 print assignments[i],'\t',
>             print
>             keys = students.keys()
>             keys.sort()
>             for x in keys:
>                 print x,'\t',
>                 grades = students[x]
>                 print_grades(grades)

definiscono la funzione `print_all_grades`.

Notate come le chiavi vengano innanzitutto estratte dal dizionario `students` con la funzione di `keys` contenuta nella linea: `keys = students.keys()` . `keys` è una lista, quindi possono essere usate tutte le funzioni delle liste. Successivamente vengono ordinate le chiavi nella linea `keys.sort()` e viene utilizzato un ciclo `for` per scorrere tutte le chiavi. I voti sono immagazzinati come una lista all'interno del dizionario in modo che l'assegnamento `grades = students[x]` assegni a `grades` la lista immagazzinata nella chiave `x`. La funzione `print_grades` visualizza semplicemente una lista ed è definita poche linee sotto.

Le ultime linee del programma implementano le varie opzioni del menu. La linea `students[name] = [0] * len(max_points)` aggiunge uno studente alla chiave corrispondente al nome. La notazione `[0] * len(max_points)` crea una array di '0' della stessa lunghezza della lista `max_points`.

La scelta "remove students" cancella uno studente in modo simile all'esempio precedente. La scelta "record grades" è più complessa. I voti vengono estratti nella linea `grades = students[name]` che ritorna un riferimento ai voti dello studente `name`. Un voto viene quindi registrato nella linea `grades[wich] = grade`. Notate che `grades` non viene inserito nel dizionario `students`. Il motivo di questa "mancanza" è che `grades` è semplicemente un altro nome per `student[name]` quindi cambiare `grades` significa cambiare `student[name]`.

# Capitolo 12. Usare i moduli

Questo è l'esercizio del capitolo (chiamatelo cal.py): [1]

>     import calendar

>     year = input("Type in the year number:")
>     calendar.prcal(year)
>      And here is part of the output I got:
>     Type in the year number:2001
>                                       2001

>            January                  February                    March
>     Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
>      1  2  3  4  5  6  7                1  2  3  4                1  2  3  4
>      8  9 10 11 12 13 14       5  6  7  8  9 10 11       5  6  7  8  9 10 11
>     15 16 17 18 19 20 21      12 13 14 15 16 17 18      12 13 14 15 16 17 18
>     22 23 24 25 26 27 28      19 20 21 22 23 24 25      19 20 21 22 23 24 25
>     29 30 31                  26 27 28                  26 27 28 29 30 31

(Ho saltato parte dell'output, credo vi siate fatti un'idea). Cosa fa il programma ? La prima linea `import calendar` usa un nuovo comando: `import` . Il comando `import` carica un modulo (in questo caso il modulo `calendar`). Per vedere i comandi disponibili nei moduli standard cercate nella "library reference" (se l'avete scaricata) o sul sito ufficiale http://www.python.org/doc/current/lib/lib.html. Il modulo calendar è descritto nel capitolo 5.9. Se leggete la documentazione vi accorgerete di una funzione chiamata `prcal` che visualizza il calendario di un anno. La linea `calendar.prcal (year)` usa la funzione descritta. Riassumendo, per utilizzare un modulo importatelo, quindi usate nome_modulo.funzione per utilizzare le funzioni del modulo. Un'altro modo per scrivere il programma:

>     from calendar import prcal

>     year = input("Type in the year number:")
>     prcal(year)

Questa versione importa una specifica funzione dal modulo. Creiamo un'altro programma utilizzando le funzioni della Python Library (chiamate il file `clock.py`)(premete 'ctrl' e 'c' per chiudere il programma):

>     from time import time, ctime

>     prev_time = ""
>     while(1):
>         the_time = ctime(time())
>         if(prev_time != the_time):
>             print "The time is:",ctime(time())
>             prev_time = the_time
>      With some output being:
>     The time is: Sun Aug 20 13:40:04 2000
>     The time is: Sun Aug 20 13:40:05 2000
>     The time is: Sun Aug 20 13:40:06 2000
>     The time is: Sun Aug 20 13:40:07 2000
>     Traceback (innermost last):
>       File "clock.py", line 5, in ?
>         the_time = ctime(time())
>     KeyboardInterrupt

L'output è ovviamente infinito, così l'ho interrotto (l'output continua fino a quando non premete 'ctrl+c'). Il programma entra semplicemente in un cliclo infinito ed esegue un controllo per vedere se l'orario è cambiato, nel qual caso visualizza il nuovo orario sul monitor. Fate attenzione a come import è utilizzato nella linea `'from time import time, ctime'` per richiamare più di una funzione.

La Python Library contiene molte funzioni utili che semplificano la programmazione in Python.

## Esercizio

Riscrivete il programma `high_low.py` della sezione 5.2 usando le ultime due cifre della funzione time per rendere il numero 'random' (casuale).

# Capitolo 13. Ancora sulle liste

Abbiamo già esaminato le liste e come vengono utilizzate. Ora che avete un background più corposo entrerò più in dettaglio. Innanzitutto scopriremo altri modi per estrarre gli elementi dalle liste, quindi analizzeremo un metodo per copiarle.

Questi sono alcuni esempi dell'utilizzo degli indici per accedere ai singoli elementi di una lista:

>     >>> list = ['zero','one','two','three','four','five']
>     >>> list[0]
>     'zero'
>     >>> list[4]
>     'four'
>     >>> list[5]
>     'five'

Questi esempi dovrebbero esservi familiari. Se volete estrarre il primo elemento di una lista dovrete richiamare l'elemento con indice 0, il secondo elemento avrà indice 1 e così via attraverso la lista. Come fare se volete l'ultimo elemento della lista ? Una via potrebbe essere quella di utilizzare la funzione `len` all'interno delle parentesi quadre: `list[len(list)-1]`. `len` ritorna sempre l'ultimo indice + 1. Nello stesso modo l'istruzione per avere il penultimo elemento della lista sarà `list[len(list)-2]`. Esiste una via più semplice: in Python l'ultimo elemento è sempre indicizzato come -1, il penultimo come -2 e così via. Ecco un'esempio:

>     >>> list[len(list)-1]
>     'five'
>     >>> list[len(list)-2]
>     'four'
>     >>> list[-1]
>     'five'
>     >>> list[-2]
>     'four'
>     >>> list[-6]
>     'zero'

Così ogni elemento in una lista può essere indicizzato in due modi differenti, dall'inizio della lista e dalla fine della lista.

Un'altra via molto utile per estrarre elementi da una lista sono le sezioni. Ecco un'altro esempio:

>     >>> list = [0,'Fred',2,'S.P.A.M.','Stocking',42,"Jack","Jill"]
>     >>> list[0]
>     0
>     >>> list[7]
>     'Jill'
>     >>> list[0:8]
>     [0, 'Fred', 2, 'S.P.A.M.', 'Stocking', 42, 'Jack', 'Jill']
>     >>> list[2:4]
>     [2, 'S.P.A.M.']
>     >>> list[4:7]
>     ['Stocking', 42, 'Jack']
>     >>> list[1:5]
>     ['Fred', 2, 'S.P.A.M.', 'Stocking']

Le sezioni sono utilizzate per estrarre parti di liste. La sintassi per estrarre sezioni è `list[primo_indice:ultimo_indice]`. La sezione selezionata va da `primo_indice` all'indice prima di `ultimo_indice`. E' possibile utilizzare entrambi i metodi di indicizzazione:

>     >>> list[-4:-2]
>     ['Stocking', 42]
>     >>> list[-4]
>     'Stocking'
>     >>> list[-4:6]
>     ['Stocking', 42]

Un'altro trucco con le sezioni è non specificare l'indice. Se il primo indice non viene specificato Python assumerà il primo indice della lista come indice da cui partire: Ecco un'altro esempio:

>     >>> list[:2]
>     [0, 'Fred']
>     >>> list[-2:]
>     ['Jack', 'Jill']
>     >>> list[:3]
>     [0, 'Fred', 2]
>     >>> list[:-5]
>     [0, 'Fred', 2]

Ancora un'altro programma d'esempio:

>     poem = \
>     ["<B>","Jack","and","Jill","</B>","went","up","the","hill","to","<B>",\
>     "fetch","a","pail","of","</B>","water.","Jack","fell","<B>","down","and",\
>     "broke","</B>","his","crown","and","<B>","Jill","came","</B>","tumbling",\
>     "after"]

>     def get_bolds(list):
>             true = 1
>             false = 0
>             ## is_bold tells whether or not the we are currently looking at
>             ## a bold section of text.
>             is_bold = false
>             ## start_block is the index of the start of either an unbolded
>             ## segment of text or a bolded segment.
>             start_block = 0
>             for index in range(len(list)):
>                     ##Handle a starting of bold text
>                     if list[index] == "<B>":
>                             if is_bold:
>                                     print "Error:  Extra Bold"
>                             ##print "Not Bold:",list[start_block:index]
>                             is_bold = true
>                             start_block = index+1
>                     ##Handle end of bold text
>                     if list[index] == "</B>":
>                             if not is_bold:
>                                     print "Error: Extra Close Bold"
>                             print "Bold [",start_block,":",index,"] ",\
>                             list[start_block:index]
>                             is_bold = false
>                             start_block = index+1

>     get_bolds(poem)

E questo è l'output:

>     Bold [ 1 : 4 ]  ['Jack', 'and', 'Jill']
>     Bold [ 11 : 15 ]  ['fetch', 'a', 'pail', 'of']
>     Bold [ 20 : 23 ]  ['down', 'and', 'broke']
>     Bold [ 28 : 30 ]  ['Jill', 'came']

La funzione `get_bold` scorre per una lista dividendola in parole e chiamate. Le chiamate che cerca sono `<B>` che inizia il testo in grassetto e `<\B>` che lo termina.

La prossima funzione delle liste è copiarle:

>     >>> a = [1,2,3]
>     >>> b = a
>     >>> print b
>     [1, 2, 3]
>     >>> b[1] = 10
>     >>> print b
>     [1, 10, 3]
>     >>> print a
>     [1, 10, 3]

Questo è probabilmente sorprendente in quanto una modifica a `b` modifica anche `a`. Questo grazie all'istruzione `b = a` che restituisce `b` come riferimento ad `a`. Significa che `b` non è altro che un'altro nome per riferirsi ad `a`, il risultato è che una modifica a `b` è una modifica ad `a`. Ciò nonostante alcune tipologie di assegnamento non significano la creazione di un doppio riferimento:

>     >>> a = [1,2,3]
>     >>> b = a*2
>     >>> print a
>     [1, 2, 3]
>     >>> print b
>     [1, 2, 3, 1, 2, 3]
>     >>> a[1] = 10
>     >>> print a
>     [1, 10, 3]
>     >>> print b
>     [1, 2, 3, 1, 2, 3]

In questo caso `b` non è un riferimento ad `a` in quanto l'istruzione `a*2` crea una nuova lista; `b` quindi si riferisce ad `a*2` e non ad `a`. Tutti gli assegnamenti creano un riferimento. Quando passate una lista come argomento ad una funzione create un riferimento. La maggior parte delle volte non dovrete preoccuparvi di creare un riferimento anziché una copia. Ciò nonostante, quando dovete modificare una lista senza cambiarne un'altra assegnata ad un nome differente, dovete assicurarvi di aver creato una copia e non un riferimento. Esistono diversi modi per copiare una lista. Il modo più semplice è usare le sezioni:

>     >>> a = [1,2,3]
>     >>> b = a[:]
>     >>> b[1] = 10
>     >>> print a
>     [1, 2, 3]
>     >>> print b
>     [1, 10, 3]

In questo modo si può copiare una lista, ma qualsiasi sottolista creata in seguito si riferirà alla rispettiva sottolista della lista originale. Potete ovviare al problema copiando anche le sottoliste usando la funzione `deepcopy` del modulo `copy` :

>     >>> import copy
>     >>> a = [[1,2,3],[4,5,6]]
>     >>> b = a[:]
>     >>> c = copy.deepcopy(a)
>     >>> b[0][1] = 10
>     >>> c[1][1] = 12
>     >>> print a
>     [[1, 10, 3], [4, 5, 6]]
>     >>> print b
>     [[1, 10, 3], [4, 5, 6]]
>     >>> print c
>     [[1, 2, 3], [4, 12, 6]]

Innanzitutto notate che `a` è una lista di liste. L'istruzione `b[0][1] = 10` cambia sia la lista `b` che la lista `a`, `c` invece resta uguale. Questo accade perché `b` continua ad essere un riferimento ad `a` se vengono utilizzate le sezioni; `c` invece è una copia ottenuta grazie alla funzione `deepcopy`.

Dovrete preoccuparvi dei riferimenti solamente quando utilizzate dizionari e liste. Numeri e stringhe creano dei riferimenti ma quando vengono modificati creano una copia, quindi non potrete mai modificarli inaspettatamente.

Adesso vi starete probabilmente chiedendo perché vengono usati i riferimenti. La ragione basilare è per la loro velocità. E' molto più veloce fare un riferimento a una lista di migliaia di riferimenti che copiarli tutti. Un'altra ragione è che permettono di avere una funzione che modifichi una lista o un dizionario. Tenetene quindi conto se vi troverete ad avere strani errori in relazione a dati modificati quando quest'ultimi non avrebbero dovuto subire alcun cambiamento.

# Capitolo 14. La vendetta delle stringhe

Ora presenteremo un trucco che può essere usato con le stringhe:

>     def shout(string):
>         for character in string:
>             print "Gimme a "+character
>             print "'"+character+"'"

>     shout("Lose")

>     def middle(string):
>         print "The middle character is:",string[len(string)/2]

>     middle("abcdefg")
>     middle("The Python Programming Language")
>     middle("Atlanta")

Ecco l'output:

>     Gimme a L
>     'L'
>     Gimme a o
>     'o'
>     Gimme a s
>     's'
>     Gimme a e
>     'e'
>     The middle character is: d
>     The middle character is: r
>     The middle character is: a

Questo programma dimostra che le stringhe sono per alcuni aspetti simili alle liste. La procedura `shout` dimostra che un ciclo `for` può essere usato con le stringhe esattamente nello stesso modo in cui veniva usato con le liste. La procedura `middle` mostra come possa essere utilizzata la funzione `len` anche con le stringhe, così come gli indici e le slice. Molte funzioni delle liste funzionano con le stringhe.

La prossima funzione utilizzerà alcune funzioni specifiche delle stringhe:

>     def to_upper(string):
>         ## Converts a string to upper case
>         upper_case = ""
>         for character in string:
>             if 'a' <= character <= 'z':
>                 location = ord(character) - ord('a')
>                 new_ascii = location + ord('A')
>                 character = chr(new_ascii)
>             upper_case = upper_case + character
>         return upper_case

>     print to_upper("This is Text")

Con l'output:

>     THIS IS TEXT

Il motivo per cui questo codice funziona è che il computer "vede" le lettere come numeri da 0 a 255. Python ha una funzione `ord` (abbreviazione di ordinale) che ritorna un carattere come un numero. Esiste anche una funzione corrispondente `chr` che converte un numero in un carattere. Imparate queste funzioni, il programma dovrebbe essere chiaro. Il primo dettaglio è la linea: `if 'a' <= character <= 'z':` che controlla se la lettera è minuscola. La linea: `location = ord(character) - ord('a')` converte i numeri corrispondenti alle lettere nel codice ASCII in numeri da 0 a 36 quindi la linea `new_ascii = location + ord('A')` converte la lettera minuscola in maiuscola.

Un'altro esercizio:

>     >>> #Integer to String
>     ...
>     >>> 2
>     2
>     >>> repr(2)
>     '2'
>     >>> -123
>     -123
>     >>> repr(-123)
>     '-123'
>     >>> #String to Integer
>     ...
>     >>> "23"
>     '23'
>     >>> int("23")
>     23
>     >>> "23"*2
>     '2323'
>     >>> int("23")*2
>     46
>     >>> #Float to String
>     ...
>     >>> 1.23
>     1.23
>     >>> repr(1.23)
>     '1.23'
>     >>> #Float to Integer
>     ...
>     >>> 1.23
>     1.23
>     >>> int(1.23)
>     1
>     >>> int(-1.23)
>     -1
>     >>> #String to Float
>     ...
>     >>> float("1.23")
>     1.23
>     >>> "1.23"
>     '1.23'
>     >>> float("123")
>     123.0

Se non l'avete ancora indovinato la funzione `repr` converte un intero in stringa e la funzione `int` converte una stringa in intero. La funzione `float` converte una stringa in un numero in virgola mobile. La funzione `repr` ritorna una rappresentazione stampabile di qualcosa. Ecco alcuni esempi:

>     >>> repr(1)
>     '1'
>     >>> repr(234.14)
>     '234.14'
>     >>> repr([4,42,10])
>     '[4, 42, 10]'

La funzione `int` prova a convertire una stringa (o un numero in virgola mobile) in un intero. Esiste anche una funzione simile `float` che converte un numero intero in numero in virgola mobile. Un'altra funzione di Python è `eval` che ritorna il tipo di dato che viene immesso. Per esempio:

>     >>> v=eval('123')
>     >>> print v,type(v)
>     123 <type 'int'>
>     >>> v=eval('645.123')
>     >>> print v,type(v)
>     645.123 <type 'float'>
>     >>> v=eval('[1,2,3]')
>     >>> print v,type(v)
>     [1, 2, 3] <type 'list'>

Se usate la funzione `eval` dovete controllare il valore che ritorna per assicurarvi che sia quello che vi aspettate.

Un'altra funzione utile in `string` è la funzione `split`. Questo è un esempio:

>     >>> import string
>     >>> string.split("This is a bunch of words")
>     ['This', 'is', 'a', 'bunch', 'of', 'words']
>     >>> string.split("First batch, second batch, third, fourth",",")
>     ['First batch', ' second batch', ' third', ' fourth']

Notate come `split` converte una stringa in una lista di stringhe. La stringa viene divisa in corrispondenza di ogni spazio o di un secondo argomento (in questo caso la virgola).

## Esempi

>     #Questo programma richiede un'eccellente conoscenza dei numeri decimali
>     def to_string(in_int):
>         "Converts an integer to a string"
>         out_str = ""
>         prefix = ""
>         if in_int < 0:
>             prefix = "-"
>             in_int = -in_int
>         while in_int / 10 != 0:
>             out_str = chr(ord('0')+in_int % 10) + out_str
>             in_int = in_int / 10
>         out_str = chr(ord('0')+in_int % 10) + out_str
>         return prefix + out_str

>     def to_int(in_str):
>         "Converts a string to an integer"
>         out_num = 0
>         if in_str[0] == "-":
>             multiplier = -1
>             in_str = in_str[1:]
>         else:
>             multiplier = 1
>         for x in range(0,len(in_str)):
>             out_num = out_num * 10 + ord(in_str[x]) - ord('0')
>         return out_num * multiplier

>     print to_string(2)
>     print to_string(23445)
>     print to_string(-23445)
>     print to_int("14234")
>     print to_int("12345")
>     print to_int("-3512")

Ecco l'output:

>     2
>     23445
>     -23445
>     14234
>     12345
>     -3512

# Capitolo 15. File IO

Questo è un semplice esempio di File IO:

>     #Write a file
>     out_file = open("test.txt","w")
>     out_file.write("This Text is going to out file\nLook at it and see\n")
>     out_file.close()

>     #Read a file
>     in_file = open("test.txt","r")
>     text = in_file.read()
>     in_file.close()

>     print text,

L'output e i contenuti del file test.txt sono:

>     This Text is going to out file
>     Look at it and see

Osservate come il programma scriva un file chiamato `test.txt` nella directory nella quale viene eseguito. Il `"\n"` nella stringa dice a Python di andare a capo nel punto in cui compare.

Una panoramica sul file IO:

1. Aprite un oggetto file con la funzione `open`

2. Leggete o scrivete nell'oggetto file (dipendentemente da come l'avete aperto)

3. Chiudetelo

Il primo passo è usare un oggetto file grazie alla funzione `open`. La sintassi è `oggetto_file = open (nome_file, modo)` dove `oggetto_file` è la variabile contenente l'oggetto file, `nome_file` la stringa con il nome del file, e `modo` la modalità di apertura del file: `"r"` in lettura, `"w"` in scrittura. Dopodiché potrete chiamare le funzioni dell'oggetto file. Le due funzioni più comuni sono `read` e `write`: la funzione `read` legge il file e ne ritorna il contenuto sottoforma di stringa, la funzione `write` aggiunge una stringa alla fine del file.

Questa è una nuova versione dell'agenda telefonica che abbiamo scritto precedentemente:

>     import string

>     def print_numbers(numbers):
>         print "Telephone Numbers:"
>         for x in numbers.keys():
>             print "Name: ",x," \tNumber: ",numbers[x]
>         print

>     def add_number(numbers,name,number):
>         numbers[name] = number

>     def lookup_number(numbers,name):
>         if numbers.has_key(name):
>             return "The number is "+numbers[name]
>         else:
>             return name+" was not found"

>     def remove_number(numbers,name):
>         if numbers.has_key(name):
>             del numbers[name]
>         else:
>             print name," was not found"

>     def load_numbers(numbers,filename):
>         in_file = open(filename,"r")
>         while 1:
>             in_line = in_file.readline()
>             if in_line == "":
>                 break
>             in_line = in_line[:-1]
>             [name,number] = string.split(in_line,",")
>             numbers[name] = number
>         in_file.close()

>     def save_numbers(numbers,filename):
>         out_file = open(filename,"w")
>         for x in numbers.keys():
>             out_file.write(x+","+numbers[x]+"\n")
>         out_file.close()

>     def print_menu():
>         print '1. Print Phone Numbers'
>         print '2. Add a Phone Number'
>         print '3. Remove a Phone Number'
>         print '4. Lookup a Phone Number'
>         print '5. Load numbers'
>         print '6. Save numbers'
>         print '7. Quit'
>         print

>     phone_list = {}
>     menu_choice = 0
>     print_menu()
>     while menu_choice != 7:
>         menu_choice = input("Type in a number (1-7):")
>         if menu_choice == 1:
>             print_numbers(phone_list)
>         elif menu_choice == 2:
>             print "Add Name and Number"
>             name = raw_input("Name:")
>             phone = raw_input("Number:")
>             add_number(phone_list,name,phone)
>         elif menu_choice == 3:
>             print "Remove Name and Number"
>             name = raw_input("Name:")
>             remove_number(phone_list,name)
>         elif menu_choice == 4:
>             print "Lookup Number"
>             name = raw_input("Name:")
>             print lookup_number(phone_list,name)
>         elif menu_choice == 5:
>             filename = raw_input("Filename to load:")
>             load_numbers(phone_list,filename)
>         elif menu_choice == 6:
>             filename = raw_input("Filename to save:")
>             save_numbers(phone_list,filename)
>         elif menu_choice == 7:
>             pass
>         else:
>             print_menu()
>     print "Goodbye"

Ora include anche il salvataggio e la lettura di files.

Output:

>     > python tele2.py
>     1. Print Phone Numbers
>     2. Add a Phone Number
>     3. Remove a Phone Number
>     4. Lookup a Phone Number
>     5. Load numbers
>     6. Save numbers
>     7. Quit

>     Type in a number (1-7):2
>     Add Name and Number
>     Name:Jill
>     Number:1234
>     Type in a number (1-7):2
>     Add Name and Number
>     Name:Fred
>     Number:4321
>     Type in a number (1-7):1
>     Telephone Numbers:
>     Name:  Jill     Number:  1234
>     Name:  Fred     Number:  4321

>     Type in a number (1-7):6
>     Filename to save:numbers.txt
>     Type in a number (1-7):7
>     Goodbye

>     > python tele2.py
>     1. Print Phone Numbers
>     2. Add a Phone Number
>     3. Remove a Phone Number
>     4. Lookup a Phone Number
>     5. Load numbers
>     6. Save numbers
>     7. Quit

>     Type in a number (1-7):5
>     Filename to load:numbers.txt
>     Type in a number (1-7):1
>     Telephone Numbers:
>     Name:  Jill     Number:  1234
>     Name:  Fred     Number:  4321

>     Type in a number (1-7):7
>     Goodbye

Le nuove porzioni del programma sono:

>     def load_numbers(numbers,filename):
>         in_file = open(filename,"r")
>         while 1:
>             in_line = in_file.readline()
>             if len(in_line) == 0:
>                 break
>             in_line = in_line[:-1]
>             [name,number] = string.split(in_line,",")
>             numbers[name] = number
>         in_file.close()

>     def save_numbers(numbers,filename):
>         out_file = open(filename,"w")
>         for x in numbers.keys():
>             out_file.write(x+","+numbers[x]+"\n")
>         out_file.close()

Analiziamo la funzione `save_numbers` del programma. Innanzitutto crea un oggetto file con il comando `open(filename, "w")` dopodiché crea una nuova linea per ognuno dei numeri di telefono con il comando `out_file.write(x+","+nombers[x]+"\n")`. In questo modo scrive una linea contenente il nome, una virgola ed il numero, seguito da un 'a capo' (newline).

La funzione `load_numbers` è un po' più complessa. Inizia creando un oggetto file quindi usa un ciclo `while` per scorrere il file e leggere le linee con l'istruzione `in_line = in_file.readline()` finché non incontra un `break`. L'istruzione `if` esegue un controllo e uscirà dal ciclo `while` con una istruzione `break` nel momento in cui incontrerà la fine del `file (len(in_line) == 0)` .

L'istruzione `in_line = in_line[:-1]` elimina l'ultimo carattere della linea (il newline che farebbe andare a capo la linea) e nelle restanti istruzioni viene trattata la stringa dividendola in base alla virgola in due parti: `[name,number] = string.split(in_line,",")` , nome e numero. Infine il numero viene inserito nel dizionario `numbers`.

## Esercizi

Modificate il programma dei voti del Capitolo 11 per salvare su di un file la registrazione degli studenti.

# Capitolo 16. Occuparsi dell'imperfetto (o come gestire gli errori)

Ora avete un programma perfetto, funziona senza crepe, ad eccezione di un dettaglio: va in crash se l'utente inserisce un input errato. Non abbiate paura, Python ha una speciale struttura di controllo per eliminare questi imprevisti. Sto parlando di `try`: `try` tenta di fare qualcosa. Segue un esempio di un programma che contiene un problema:

>     print "Type Control C or -1 to exit"
>     number = 1
>     while number != -1:
>         number = int(raw_input("Enter a number: "))
>         print "You entered: ",number

Se tentate di inserire qualcosa come `#@&` l'output sarà simile a questo:

>     Traceback (innermost last):
>       File "try_less.py", line 4, in ?
>         number = int(raw_input("Enter a number: "))
>     ValueError: invalid literal for int(): @#&

Come potete vedere la funzione `int()` non funziona (e non deve funzionare) con il 'numero' `#@&`. L'ultima linea mostra qual'è l'errore: Python ha trovato un `ValueError`. Come fare in modo che il nostro programma sappia gestire anche questo valore ? Innanzitutto mettendo la parte di codice che restituisce l'errore in un blocco `try` e poi decidendo come Python debba trattare `ValueError`. Il seguente programma mostra come ottenere tale comportamento:

>     print "Type Control C or -1 to exit"
>     number = 1
>     while number != -1:
>         try:
>             number = int(raw_input("Enter a number: "))
>             print "You entered: ",number
>         except ValueError:
>             print "That was not a number."

Ora, quando eseguiremo il nuovo programma ed inseriremo `#@&` il programma risponderà con la frase `"That was not a number."` per poi continuare ciò che stava facendo prima.

Quando il vostro programma restituisce un errore che sapete come gestire, mettete il codice in un blocco `try` e il modo per gestire l'errore nel successivo blocco `except`.

## Esercizi

Aggiornate il programma della rubrica telefonica del capitolo precedente in modo che non fermi l'esecuzione se l'utente non inserisce dati nel menu.

# Capitolo 17. Fine

Sto lavorando per aggiungere ulteriori sezioni a questo documento. Per ora vi raccomando il "Python Tutorial" di Guido Van Rossum, dovreste essere in grado di capire la maggior parte degli argomenti.

Questo tutorial è ancora un lavoro in corso. Gradirei ogni commento e ogni richiesta di argomenti da aggiungere. Le vostre e-mail mi hanno portato ad ampliare e migliorare notevolmente il documento, ascoltando sempre molto attentamente ogni vostro commento :).

Buona programmazione, che possa cambiare la vostra vita e il mondo.

# Capitolo 18. FAQ

Scherzetto ... le FAQ non sono state tradotte ;-)

Niente paura, semplicemente erano così stringate che, per ora, è stato ritenuto più opportuno impostarle in altro modo. In due parole ... suggerivano di usare una versione di Python 2.1 o superiori e davano indicazioni su dove trovare la versione originale di questo tutorial ed i formati disponibili.

In merito all'ubicazione del tutorial, per quanto riguarda la versione originale:

http://www.honors.montana.edu/~jjc/easytut/

All'URL indicata è possibile reperire il documento in molteplici formati, html, ps, pdf, ps e pdf Book, il make per crearli e logicamente il sorgente in formato .tex. Come molti di voi avranno capito il sorgente è stato scritto in LaTeX, usando però la classe "manual", presa direttamente da quella creata dal gruppo Python per scrivere la documentazione del linguaggio.

Inoltre è disponibile l'elenco delle versioni rilasciate dall'autore:

  2000-Dec-16, added error handling chapter.
  2000-Dec-22, Removed old install procedure.
  2001-Jan-16, Fixed bug in program, Added example and data to lists section.
  2001-Apr-5, Spelling, grammar, added another how to break programs, url fix for PDF version.
  2001-May-13, Added chapter on debugging.
  2001-Nov-11, Added exercises, fixed grammar, spelling, and hopefully improved explanations of some things.
  2001-Nov-19, Added password exercise, revised references section.
  2002-Feb-23, Moved 3 times password exercise, changed l to list in list examples question.
  Added a new example to Decisions chapter, added two new exercises.
  2002-Mar-14, Changed abs to my_abs since python now defines a abs function.

Per quanto riguarda la presente versione, tradotta in Italiano, c'è poco da dire ... in questo momento ancora non c'è un singolo, univoco sito dove si può dire che potrà essere sicuramente trovato questo documento, anche se molto probabilmente sarà disponibile sul sito Italiano di Python:

http://www.python.it

Per quanto riguarda le caratteristiche del documento la traduzione è avvenuta piuttosto fedelmente ma altrettanto non si può dire per il software utilizzato per la stesura vera e propria. Difatti, invece di usare LaTeX è stato usato il più comune SGML con DocBook. Quindi il risultato è un semplice file sgml che potrà essere convertito agevolmente in ogni formato disponibile.

A questo proposito sarebbe cosa gradita che chiunque volesse rendere disponibile il presente tutorial sul proprio sito, quantomeno rilasciasse le versioni html formato DocBook, html in unica pagina, txt, ps, ps bookshleet, pdf, un file compresso contenente una directory che racchiuda i formati elencati ed il sorgente sgml. Per semplificare il procedimento è stato realizzato un Makefile che converte nei formati elencati e contiene semplici istruzioni per utilizzare al meglio il bookshleet.ps permettendo la creazione distinta delle pagine pari e di quelle dispari destinate alla stampa.

### Note

[1] | Import cerca un file di nome `calendar.py` e lo legge. Se il file chiamante si chiama `calendar.py` e contiene `'import calendar'` cerca di leggere in se stesso con risultati quantomeno scarsi.