Subsections

7. Definire le Funzioni

7.1 Creare funzioni

Inizierò questo capitolo mostrandovi, con un esempio, 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"
Con questo output:
The absolute values of 23 and 23 are equal
Il programma sembra un po' ripetitivo (e i programmatori odiano ripetere le cose, altrimenti i computer a cosa servono??). 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"
Con questo 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 my_abs. Poi troviamo una ``(`` seguita dal parametro num (num 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. Quando l'indentazione torna al livello della funzione o quando incontra l'istruzione return la funzione termina. L'istruzione return ritorna il valore assunto nel punto in cui è chiamata nella funzione.

Osservate che i valori a e b non sono cambiati. Le funzioni, naturalmente, possono essere usate anche per ripetere azioni che non ritornano alcun valore. Eccone alcuni esempi:

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)
Con questo 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 utilizzare le funzioni. Osservate attentamente, potete anche non dare argomenti ad una funzione, così come potete dargliene più d'uno. Notate anche che return è opzionale.

7.2 Variabili nelle funzioni

Naturalmente troverete spesso variabili nel codice duplicato che andrete ad eliminare. Queste variabili vengono trattate da Python in modo speciale. Fino ad ora tutte le variabili che abbiamo visto erano variabili globali. Le funzioni usano variabili particolari chiamate variabili locali. Queste variabili esistono solamente per la durata della funzione. Quando una variabile locale ha lo stesso nome di una variabile globale, la variabile locale nasconde l'altra variabile. Siete confusi? Beh, il prossimo esempio dovrebbe chiarire un po' le cose.

a_var = 10
b_var = 15
e_var = 25

def a_func(a_var):
    print "in a_func a_var = ",a_var
    b_var = 100 + a_var
    d_var = 2*a_var
    print "in a_func b_var = ",b_var
    print "in a_func d_var = ",d_var
    print "in a_func e_var = ",e_var
    return b_var + 10

c_var = a_func(b_var)

print "a_var = ",a_var
print "b_var = ",b_var
print "c_var = ",c_var
print "d_var = ",d_var

L'output è:

in a_func a_var =  15
in a_func b_var =  115
in a_func d_var =  30
in a_func e_var =  25
a_var =  10
b_var =  15
c_var =  125
d_var = 
Traceback (innermost last):
  File "separate.py", line 20, in ?
    print "d_var = ",d_var
NameError: d_var

In questo esempio le variabili a_var, b_var e d_var sono variabili locali quando sono all'interno della funzione a_func. Dopo che l'istruzione return b_var + 10 viene eseguita, non esisteranno più. La variabile a_var è automaticamente una variabile locale, dato che è un nome di parametro. Le variabili b_var e d_var sono variabili locali, dato che compaiono nella parte sinistra di un assegnamento, all'interno della funzione nelle istruzioni b_var = 100 + a_var e d_var = 2*a_var.

All'interno della funzione a_var è 15 finché la funzione viene chiamata con a_func(b_var). Visto che fino a quel punto b_var corrisponde a 15, la chiamata alla funzione è a_func(15), che di conseguenza assegna 15 ad a_var all'interno di a_func.

Come potete vedere, nel momento in cui la funzione finisce di essere eseguita, le variabili locali a_var e b_var, che fino a quel momento hanno nascosto le variabili globali con lo stesso nome, sono svanite. Quindi l'istruzione print "a_var = ",a_var restituisce il valore 10 piuttosto che 15, proprio perché la variabile locale non esiste più.

Un'altra cosa da notare è il NameError che avviene alla fine. Questo errore è dovuto al fatto che la variabile d_var non esiste più. Tutte le varibili locali vengono cancellato quando si esce dalla a_funzione in cui sono state definite. Se volete ritornare un valore da una funzione dovete usare return qualcosa.

L'ultimo particolare è che il valore di e_var rimane invariato all'interno di a_func, visto che non è un parametro e non viene ridefinito all'interno della funzione a_func. Quando si accede ad una variabile globale dall'interno di una funzione, è come accedervi dall'esterno, rimane invariata.

Le funzioni permettono alle variabili locali di esistere solo ed unicamente all'interno della funzione stessa, e possono nascondere le altre variabili definite all'esterno della funzione.

7.3 Analizzare le funzioni

Ora esamineremo il seguente programma linea per linea:

def mult(a,b):
    if b == 0:
        return 0
    rest = mult(a,b - 1)
    value = a + rest
    return value

print "3*2 = ",mult(3,2)

Il programma crea una funzione che moltiplica un intero positivo (il che è nettamente più lento rispetto alla funzione di moltiplicazione built-in), dopodiché ne dimostra l'utilizzo.

Domanda: Qual'è la prima cosa che fa il programma?

Risposta: La prima cosa che fa è definire la funzione mult() con queste linee:

def mult(a,b):
    if b == 0:
        return 0
    rest = mult(a,b - 1)
    value = a + rest
    return value
Queste righe realizzano una funzione che prende due parametri e ritornano un valore. Più tardi questa funzione sarà eseguita.

Domanda: Ed ora cosa succede?

Risposta: Viene eseguita la linea successiva dopo la funzione, print "3*2 = ",mult(3,2).

Domanda: E cosa fa?

Risposta: Stampa 3*2 = e ritorna il valore di mult(3,2)

Domanda: E cosa ritorna mult(3,2)?

Risposta: Esaminiamo la funzione mult passo per passo per scoprirlo. Alla variabile a viene assegnato il valore 3 mentre alla variabile b viene assegnato il valore 2.

Domanda: E poi?

Risposta: La linea if b == 0: viene eseguita. Visto che b ha il valore 2 la condizione è falsa e return 0 viene saltato.

Domanda: E poi?

Risposta: La linea rest = mult(a,b - 1) viene eseguita. Questa linea assegna la variabile locale rest al valore ritornato da 'mult(a,b - 1). Il valore di a è 3 e il valore di b è 2 quindi la chiamata di funzione è mult(3,1).

Domanda: Quindi qual'è il valore di mult(3,1)?

Risposta: Dobbiamo eseguire la funzione mult con i parametri 3 ed 1.

Domanda: Ovvero?

Risposta: Le variabili locali nella nuova esecuzione della funzione hanno valori differenti: a ha il valore 3, mentre b ha il valore 1. Dato che sono variabili locali esse non hanno nulla a che vedere con i precedenti valori di a e b.

Domanda: E quindi?

Risposta: Visto che b ha il valore 1 la condizione if è falsa, quindi la linea successiva diventa rest = mult(a,b - 1).

Domanda: Cosa fa questa linea?

Risposta: Questa linea assegnerà il valore di 'mult(3,0) a rest.

Domanda: E qual'è il suo valore?

Risposta: Dobbiamo calcolare la funzione un'altra volta, questa volta con i valori 3 per a e 0 per b.

Domanda: Cosa succede ora?

Risposta: La prima linea della funzione ad essere eseguita è if b == 0:. b ha il valore 0 e quindi la condizione risulta vera. Quindi la prossima linea da eseguire è return 0.

Domanda: E cosa fa la linea return 0?

Risposta: Ritorna il valore 0 all'esterno della funzione.

Domanda: Quindi?

Risposta: Quindi ora sappiamo che il risultato di mult(3,0) è 0. Ora che abbiamo un valore di ritorno possiamo tornare a mult(3,1), assegnando alla variabile rest il valore 0.

Domanda: Che linea viene eseguita ora?

Risposta: La linea value = a + rest, dove a=3 e rest=0, quindi value=3.

Domanda: Cosa succede adesso?

Risposta: La linea return value viene eseguita. Questa linea ritorna il valore 3 ed esce dalla funzione mult(3,1). Dopo che return viene eseguito, torniamo alla funzione mult(3,2).

Domanda: Dove eravamo in mult(3,2)?

Risposta: Avevamo le variabili a=3, b=2 e stavamo esaminando la linea rest = mult(a,b - 1).

Domanda: Cosa succede ora?

Risposta: La variabile rest assume il valore 3. La prossima linea value = a + rest assegna a value il valore di 3+3, ovvero 6.

Domanda: E ora?

Risposta: La prossima linea viene eseguita, ovvero il valore 6 viene ritornato dalla funzione. Ora siamo tornati alla linea print "3*2 = ",mult(3,2) e il risultato finale, 6, può essere stampato sullo schermo.

Domanda: Cos'è successo in definitiva?

Risposta: Praticamente, dando per scontato che ogni numero moltiplicato per zero dia a sua volta 0, e che un numero moltiplicato per un'altro numero è sempre uguale al primo numero + il primo numero per il secondo - 1 (x * y = x + x * (y - 1)), abbiamo moltiplicato due numeri. Ciò che accade è che 3*2 viene inizialmente convertito in 3 + 3*1. Quindi 3*1 è convertito in 3 + 3*0. Sapendo che ogni numero moltiplicato per 0 risulta 0, siamo tornati indietro ed abbiamo calcolato 3 + 3*0. Conoscendo il risultato di 3*1 possiamo calcolare che 3 + 3*1 è 3 + 3, che risulta 6.

Questo è come si presenta il tutto:

3*2
3 + 3*1
3 + 3 + 3*0
3 + 3 + 0
3 + 3
6

Queste due ultime sezioni sono state scritte di recente. Se aveste dei commenti o riscontraste errori, siete pregati di spedirmi un'email. Vorrei sapere se ho passato del tempo a creare semplicemente cose incomprensibili. Se il resto del tutorial vi sembra che abbia senso, ma non questa sezione, è probabile che la colpa sia mia, mi piacerebbe saperlo. Grazie.

7.4 Esempi

factorial.py

# Definisce una funzione che calcola il fattoriale.

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

# Converte la temperatura in Fahrenheit o 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:")

Semplice 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

# Di 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)

Semplice 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

7.5 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). Il programma deve includere anche un'interfaccia a menu.