Una funzione è soltanto un pezzo di programma cui viene dato un nome.
Riprendiamo in esame l'esempio degli “scrittori”:

risposta1 = raw_input ("chi e' l'autore dei Promessi Sposi? ")
if risposta1 == "Manzoni":
       print "la risposta e' esatta"
       print "bravo!!"
else:
       print "risposta errata!"
       print "la risposta esatta e': Manzoni"
       print "Studia di più"
risposta2 = raw_input ("chi e' l'autore della Divina Commedia? ")
if risposta2 == "Dante":
       print "la risposta è esatta"
       print "bravo!!"
else:
       print "risposta errata!"
       print "la risposta esatta è: Dante"
       print "Studia di più"

Hai osservato come il programmatore nel trattare la seconda risposta ripete molte cose che aveva già scritto per la prima ? Questo non è né comodo né veloce. Fortunatamente esiste in Python, come in molti altri linguaggi di programmazione, un meccanismo semplice per specificare una sola volta delle operazioni ricorrenti e per richiamare quelle operazioni ogni volta che ci servono.

Questo meccanismo è la “funzione”

Le funzioni sono utili quando dobbiamo far eseguire al computer più volte le stesse operazioni perché queste si possono scrivere una sola volta nella funzione. Questa sarà identificata con un nome. Ogni volta che abbiamo bisogno di eseguire quelle operazioni chiamiamo la funzione, scrivendo semplicemente il suo nome.
Possiamo immaginare la funzione come un “cameriere” (in gergo tecnico tra gli informatici si chiama “servente”) al quale si insegnano certe mansioni da svolgere in casa.
Ad esempio, al cameriere si spiega come “preparare la colazione” nel modo seguente:

  1. prepara i croissant
  2. fai il caffè
  3. scalda il latte

Dopo averlo spiegato una volta non e' più necessario ripetere tutte le volte gli ordini 1, 2 e 3 ma basta chiedere al cameriere di “preparare la colazione”.

Se il cameriere svolge anche le funzioni di cuoco, noi gli spieghiamo una ricetta per fare gli spaghetti alla carbonara che ci piacciono tanto e gliela scriviamo su un foglio. Ogni volta che vogliamo mangiare gli spaghetti alla carbonara gli diciamo semplicemente “spaghetti alla carbonara”. A questo punto il cuoco si rilegge la ricetta ed esegue le operazioni elementari descritte (fai bollire l'acqua, aggiungi il sale, ecc. ecc.).
Nel caso del nostro esempio del programma degli “scrittori” si deve chiedere al cameriere, ossia alla funzione, di eseguire le seguenti operazioni:

  1. porre la domanda e acquisire la risposta
  2. verificare se la risposta data e' uguale a quella corretta
  3. se la risposta e' corretta, visualizzare il messaggio di congratulazioni
  4. se la risposta e' errata, visualizzare il messaggio di rimprovero e il
    messaggio per ricordare la risposta corretta.

Il nostro “cameriere”, ossia la funzione, dovrà eseguire proprio queste operazioni ogni volta che porremo una nuova domanda. Al cameriere, ossia alla funzione, sarà sufficiente indicare la domanda e la risposta esatta.
In pratica dobbiamo scrivere un breve programma che esegua le operazioni che abbiamo elencato, dopo aver dato il nome alla funzione e alle scatole (ossia alle variabili) di cui la funzione avrà bisogno.
La nostra funzione si chiamerà “interrogazione”.
domanda sarà la scatola contenente la domanda.
risposta_esatta sarà la scatola destinata a contenere la risposta esatta.
Tutto questo andrà scritto su una sola riga, che sarà la prima linea della funzione.

def interrogazione (domanda, risposta_esatta)
Questa linea indica all'interprete che vogliamo definire un blocco di istruzioni che potrà essere eseguito a richiesta in un qualunque altro punto del programma semplicemente scrivendo il suo nome (interrogazione), dopo aver indicato la domanda e la risposta corretta.

Quindi la prima linea della funzione dovrà contenere:

la parolina def
(abb. ne di define, definisci) 
def 
il nome che ho deciso di dare alla
funzione
interrogazione
i nomi delle scatole su cui
lavorerà la funzione, separati da
virgole e racchiusi da parentesi
domanda
risposta_esatta

Dopo la definizione, occorre scrivere la funzione, cioè il programma che lavorerà sulle scatole indicate. Nel nostro caso:

def interrogazione (domanda, risposta_esatta):
risposta_allievo = raw_input(domanda)
if risposta_esatta == risposta_allievo:
            print "La risposta è esatta"
            print "Bravissimo"
else:
            print "Risposta errata"
            print "La risposta esatta è ", risposta_esatta
            print "studia di più!"

Confrontiamolo ora con il pezzo di programma da cui siamo partiti e che non volevamo ripetere tante volte. Notiamo subito che il codice è diventato molto più generale perché tutte le risposte sono scritte dentro delle variabili che potranno assumere valori diversi in situazioni diverse.
Mentre il programma valeva solo per domande sugli scrittori, la funzione può essere usata in un programma che pone domande di storia, di geografia, di calcio ecc. 

Programma Funzione
if risposta == "Manzoni":
  print "la risposta è esatta"
  print "bravo!!"
else:
  print "risposta errata!"
  print "la risposta esatta è:
                      Manzoni"
print "Studia di più"
def interrogazione (domanda,risposta_esatta):
 risposta_allievo = raw_input (domanda)
 if risposta_esatta == risposta_allievo:
      print "La risposta è esatta"
      print "Bravissimo"
else:
      print "Risposta errata"
      print " La risposta esatta è ",risposta_esatta
      print "studia di più!"

Si può usare qualsiasi nome per una funzione, tranne le parole riservate di Python. Le definizioni di funzione sono delle istruzioni come le altre. Tuttavia, esse saranno eseguite soltanto quando saranno chiamate.

Nota bene!!
Le istruzioni all'interno di una definizione non sono eseguite finché la funzione non viene chiamata.

CHIAMATA DI FUNZIONE
Ora dobbiamo imparare come chiamare la funzione, ossia ordinare alla funzione stessa di eseguire le operazioni in essa contenute.

In generale, la chiamata di una funzione viene effettuata scrivendo il nome della funzione, seguita dai nomi delle scatole su cui lavorare separati da virgole e racchiuse da parentesi.
Nel caso del programma che avevamo scritto avremo:

domanda1 = "chi e' l'autore dei Promessi Sposi? "
risposta_esatta1 = "Manzoni"
interrogazione (domanda1, risposta_esatta1)
domanda2 = "chi e' l'autore della Divina Commedia? "
risposta_esatta2 = "Dante"
interrogazione (domanda2, risposta_esatta2)

Fermiamoci a riflettere e a riassumere ciò che abbiamo detto finora a proposito di programmi e del flusso di esecuzione del programma.

  1. L'esecuzione inizia sempre alla prima riga del programma e le istruzioni sono eseguite una alla volta dall'alto verso il basso.
  2. Una funzione deve essere definita prima del suo uso (l'interprete deve sapere che la funzione esiste e cosa fa).
  3. La definizione di funzione non altera il flusso di esecuzione del programma e le istruzioni all'interno della funzione non sono eseguite finché questa non viene chiamata (questo vuol dire che, se definisco la funzione all'inizio del programma, l'interprete legge la definizione ma non fa nulla e prosegue nell'esecuzione del programma finché non trova la chiamata della funzione).
  4. La chiamata della funzione è una deviazione nel flusso di esecuzione:
    invece di proseguire con l'istruzione successiva, l'esecuzione salta alla prima riga della funzione chiamata ed esegue tutte le sue istruzioni; alla fine della funzione il flusso riprende dal punto dov'era stato deviato dalla chiamata di funzione. Fortunatamente Python è sufficientemente intelligente da ricordare dove il flusso di esecuzione viene via via interrotto e sa dove riprendere quando una funzione è conclusa.
  5. Quando il flusso del programma giunge all'ultima istruzione, dopo la sua esecuzione il programma è terminato.
    Ricordate che la definizione della funzione termina con l'ultima istruzione indentata.

Vediamo ora il nostro programma scritto con e senza l'uso della funzione
“interrogazione”:
(il programma è scritto in nero e la definizione di funzione in blu)

senza

con

risposta1 = raw_input("chi è l'autore dei Promessi Sposi? ")
if risposta1 == "Manzoni":
              print "la risposta è esatta"
              print "bravo!!"
else:
              print "risposta errata!"
              print "la risposta esatta è: Manzoni"
              print "Studia di più"
risposta2 = raw_input("chi è l'autore della Divina Commedia? ")
if risposta2 == "Dante":
              print "la risposta è esatta"
              print "bravo!!"
else:
              print "risposta errata!"
              print "la risposta esatta è: Dante"
              print "Studia di più'"
def interrogazione(domanda,risposta_esatta):
risposta_allievo = raw_input(domanda)
if risposta_esatta == risposta_allievo:
print "La risposta è esatta"
print "Bravissimo"
else:
print "Risposta errata"
print "La risposta esatta è ", risposta_esatta
print "Studia di più!"

domanda1 = "chi e' l'autore dei Promessi Sposi? "
risposta_esatta1 = "Manzoni"
interrogazione (domanda1, risposta_esatta1)
domanda2 = "chi e' l'autore della Divina Commedia? "
risposta_esatta2 = "Dante"
interrogazione (domanda2, risposta_esatta2)

Nota bene!
I nomi delle variabili usate nella istruzione di chiamata della funzione sono diversi dai nomi delle variabili usate nella definizione.

def interrogazione (domanda, risposta_esatta): - >DEFINIZIONE
interrogazione (domanda1, risposta_esatta1): -> CHIAMATA

Infatti la prima cosa che fa la funzione quando viene chiamata è prendere le scatole usate nella istruzione con cui è stata chiamata, scoperchiarle e mettere il loro contenuto nelle corrispondenti scatole usate all'interno della funzione.
Il contenuto di domanda1 viene scritto in domanda e il contenuto di risposta_esatta1 viene scritto in risposta_esatta.

Definizione
La funzione è una sequenza di istruzioni che esegue una determinata operazione.

Perché è necessaria questa operazione?
Le scatole all'interno della funzione sono “invisibili” all'esterno e sono utilizzate solo dentro il corpo della funzione.
In questo modo la semplice funzione che abbiamo scritto potrà essere utilizzata da voi per altri programmi o da qualche vostro amico per costruire programmi più complicati. E questo è il secondo motivo, forse il più importante, per cui si scrivono le funzioni.
I programmi attuali sono diventati cosi complicati che nessun programmatore, per quanto bravo, riuscirebbe a scriverli da solo. Qualunque programma è sempre composto per una piccola parte da nuove istruzioni e per la maggior parte da funzioni già scritte in precedenza.

Esercizi
Inserisci un numero e stampa la sua radice quadrata.

Per risolvere questo esercizio devi prima leggere questa breve spiegazione.
Ora che sai cosa sono le funzioni, devi sapere anche che Python è provvisto di una raccolta di funzioni già pronte che ti permettono di eseguire le più comuni operazioni matematiche.
La raccolta di funzioni si chiama ovviamente: math
Prima di poter usare le funzioni fornite da math, devi dire all'interprete di
caricare le funzioni in memoria.
Questa operazione, che si chiama "importazione", si scrive:

>>> import math

A questo punto hai a disposizione tutte le funzioni matematiche tra cui anche la radice quadrata. Per usare la funzione "radice quadrata" dovrai scrivere:

nome_modulo.nome_funzione (valore)
nel nostro caso sarà: math.sqrt( )

Ad esempio:

import math
print math.sqrt(4)

Soluzione:

import math
numero = input("Scrivi un numero")
print "la radice quadrata di", numero, 'è', math.sqrt(numero)

ancora funzioni…ma un po’ più difficili
l’istruzione return

In tutti gli esempi precedenti, la funzione chiamata eseguiva completamente una certa attività. A differenza dei casi precedenti, qualche volta la funzione chiamata esegue dei calcoli il cui risultato serve al programma chiamante. Vediamo un esempio:

def doppio(numero):
       numero_per_due = numero * 2
       return numero_per_due

L’istruzione return numero_per_due ordina alla funzione doppio di trasmettere al programma chiamante il valore numero_per_due.
Nel programma chiamante non si dovrà scrivere numero_per_due perché questa è una variabile della funzione e le variabili delle funzioni sono invisibili all’esterno, ma si scriverà un’istruzione del tipo:

pippo = 7 + doppio(5)

In sostanza tutto avviene come se il contenuto della scatola della funzione numero_per_due fosse trasferito nella scatola del programma principale doppio.

funzioni che chiamano funzioni

Nel corpo di una funzione si può anche scrivere una o più istruzioni che chiamino altre funzioni. Al limite, una funzione può anche chiamare se stessa.
Vediamo un esempio difficile.
Supponiamo di voler calcolare il fattoriale del numero 7. Occorre scrivere:

fatt = 7*6*5*4*3*2

La funzione che calcola il fattoriale di un numero n dovrà essere scritta come n moltiplicato per il fattoriale di (n-1); ad esempio:

fatt(7) = 7 * fatt(6)

E la funzione sarà:

def fatt(n):
       if n == 1:
           return 1
       else:
       return n * fatt(n-1)

Esercizi
Riscriviamo per comodità la funzione interrogazione:

def interrogazione (domanda,risposta_esatta):
       risposta_allievo = raw_input (domanda)
       if risposta_esatta == risposta_allievo:
         print "La risposta è esatta"
         print "Bravissimo"
else:
print "Risposta errata"
print "La risposta esatta è ", risposta_esatta
print ". Studia di più!"

Ora proviamo a inventare altre situazioni in cui questa funzione può tornare utile. Ad esempio, una interrogazione di storia.

def interrogazione (domanda,risposta_esatta):
      risposta_allievo = raw_input (domanda)
      if risposta_esatta == risposta_allievo:
      print "La risposta è esatta"
      print "Bravissimo"
    else:
      print "Risposta errata"
      print "La risposta esatta è ", risposta_esatta
      print ". Studia di più!"
domanda1 = "In che anno è caduto l'impero romano d'occidente?"
risposta_esatta1 = "476"
interrogazione (domanda1, risposta_esatta1)
domanda2 = "Chi fu il primo presidente degli Stati Uniti?"
risposta_esatta2 = "Washington"
interrogazione (domanda2, risposta_esatta2)
domanda3 = "In che anno è terminata la prima guerra mondiale?
"risposta_esatta3 = "1918"
interrogazione (domanda3, risposta_esatta3)

Vediamo alcuni esempi di funzioni che utilizzano l’istruzione return.
print “Programma che calcola il doppio di un numero”
def doppio(numero):
    numero_per_due = numero*2
    return numero_per_due
numero = input(“Inserisci un numero “)
doppio(numero)
print “il doppio è: “, numero

In questo esempio calcoliamo l’area della figura:

Scriviamo una funzione che consenta di calcolare l’area di un rettangolo.
def area_rettangolo(base, altezza):
      return base * altezza
Scriviamo una funzione che calcoli l’area di un cerchio di raggio r.
def area_cerchio(raggio):
       return 3,14 * raggio**2
Utilizziamo ora le due funzioni che abbiamo scritto per calcolare l’area della figura azzurra.
print “Programma che calcola l’area della figura azzurra”
def area_rettangolo(base, altezza):
    return base * altezza
def area_cerchio(raggio):
    return 3,14 * raggio*2
area_figura = area_rettangolo(3,2) +
area_rettangolo(5,3) + 2 * area_cerchio(1)/2
print “l’area della figura azzurra è: “, area_figura

Quest’ultimo esempio mostra come calcolare la potenza di un numero senza usare la funzione definita da Python ma usando una funzione definita da noi.
def potenza(numero, esponente):
    if esponente == 1:
          return numero
else:
          return potenza(numero,esponente-1) * numero
numero = input("Inserisci un numero ")
esponente = input("Inserisci l’esponente ")
print potenza(numero, esponente)