Le funzioni

Dove si impara come insegnare a ``Python`` a eseguire nuovi comandi.

Definire una funzione

Riprendiamo il lavoro con la grafica della Tartaruga. Se abbiamo appena avviato IDLE dobbiamo procurarci una tartaruga con le istruzioni:

>>> import pygraph.pyturtle as tg
>>> tp = tg.Turtleplane()
>>> tina = tp.newTurtle()

Riscriviamo il comando per disegnare un quadrato

>>> for i in range(4):
        tina.forward(30)
        tina.left(90)

Ora, in un programma può darsi che ci sia bisogno di disegnare molti quadrati, è scomodo e poco chiaro ripetere le tre righe scritte sopra ogni volta che serve un quadrato. Sarebbe molto più semplice avere un comando, magari di nome quadrato, che disegni un quadrato. In pratica sarebbe bello poter scrivere:

>>> quadrato()

e ottenere il disegno del quadrato al posto del messaggio:

Traceback (most recent call last):
  File "<pyshell#0>", line 1, in ?
    quadrato()
NameError: name 'quadrato' is not defined

Gli informatici hanno pensato ad un modo per esaudire questo desiderio che, evidentemente, è di tutti quelli che si mettono a programmare. Hanno realizzato un meccanismo per cui si può ampliare un linguaggio insegnandogli a eseguire comandi nuovi di nostra invenzione. Questi nuovi comandi si chiamano procedure o funzioni.

Per insegnare a Python una nuova funzione bisogna scrivere la parola riservata def seguita dal nome che vogliamo dare alla funzione, da una coppia di parentesi e dal simbolo “:” (due punti). Dopo questa riga, con un opportuno rientro (indentazione), dobbiamo scrivere tutte le istruzioni che vogliamo vengano eseguite quando si chiamerà la funzione.

Per insegnare a Python a disegnare quadrati con la tartaruga dovremo scrivere:

>>> def quadrato():
        for i in range(4):
            tina.forward(30)
            tina.left(90)

Dobbiamo terminare la scrittura della funzione premendo due volte il tasto <Invio>. Ma non succede assolutamente niente! Infatti abbiamo insegnato a disegnare un quadrato, ma non abbiamo detto a Python di disegnarlo!

Eseguire una funzione

Proviamo a dare il comando:

>>> quadrato
<function quadrato at 0x836596c>

Strano messaggio… Non è un messaggio di errore, semplicemente Python ci avvisa che quadrato è una funzione. Per dire a Python che deve eseguire la funzione quadrato dobbiamo far seguire al nome le parentesi:

>>> quadrato()

Ora va! tina ha disegnato per noi il quadrato! In modo analogo possiamo insegnare altre funzioni ad esempio per disegnare un triangolo equilatero:

>>> def triangolo():
        for i in range(3):
            tina.forward(30)
            tina.left(...)

Ovviamente al posto dei puntini devo mettere un numero: il numero di gradi dell’angolo del triangolo (quale angolo?). E poi provarlo:

>>> triangolo()

Una volta insegnata una nuova funzione possiamo utilizzarla esattamente come le funzioni primitive del linguaggio, in particolare possiamo richiamarla dall’interno di un’altra funzione:

>>> def bandierina():
        tina.forward(100)
        quadrato()
        tina.back(100)

Ripuliamo lo schermo e disegniamo la bandierina:

>>> tp.reset()
>>> bandierina()

Ovviamente possiamo scrivere una funzione che chiama una funzione che chiama una funzione, che… Possiamo, ad esempio, mettere insieme tante bandierine per costruire una girandola:

>>> def girandola():
    for i in range(36):
        bandierina()
        tina.left(10)

E poi provarla:

>>> girandola()

Troppe bandierine: modifichiamo la funzione per diminuirne il numero. Possiamo riscrivere interamente la funzione, oppure portare il cursore sopra la prima riga e premere <Invio>. La funzione viene riscritta e abbiamo la possibilità di modificarla.

>>> def girandola():
        for i in range(24):
            bandierina()
            tina.left(360./24)

Qui ho usato un trucchetto, invece di fare le divisioni a mente, le facciamo fare a Python che ha tutta la potenza del computer a disposizione. Se usiamo Python 2 dobbiamo ricordagli però di usare l’aritmetica decimale, non quella intera (360.0/24). Ripuliamo lo schermo e proviamola:

>>> tp.reset()
>>> girandola()

Ancora troppe, diminuiamole:

>>> def girandola():
    for i in range(20):
        bandierina()
        tina.left(360./20)

E proviamola:

>>> tina.reset()
>>> girandola()

Ohohoh! Proprio come volevo… A dire il vero mi sembra un po’ smorta come girandola. Un po’ di colore non guasterebbe! Modifichiamo la funzione che disegna le bandierine in modo che le disegni con il contorno marron e l’interno verde. Utilizzeremo il metodo fill(flag), quando flag vale 1 la tartaruga incomincia a segnare gli oggetti da riempire di colore, quando flag vale 0 li riempie con il colore attuale della penna.

>>> def bandierina():
        tina.color = "brown"
        tina.forward(100)
        tina.fill(1)
        quadrato()
        tina.color = "green"
        tina.fill(0)
        tina.color = "brown"
        tina.back(100)

Proviamola…

>>> tp.reset()
>>> tina.width = 4
>>> girandola()

Adesso mi piace!

Riassumendo

  • Possiamo insegnare a Python a interpretare ed eseguire comandi nuovi, la sintassi per fare ciò è:

    def <nome della funzione>():
        <istruzioni>
    
  • Una funzione scritta dal programmatore può essere utilizzata esattamente come quelle primitive del linguaggio.

  • Per eseguire una funzione devo scriverne il nome seguito da una coppia di parentesi:

    <nome della funzione>()

  • Una nuova funzione può essere richiamata da un’altra funzione e così via ricorsivamente.

  • Python 2 ha un modo un po’ suo di fare le divisioni: se dividendo e divisore sono numeri interi dà come risultato il quoziente intero troncando il risultato. Per ottenere il risultato razionale uno degli operandi deve essere un numero con la virgola (il punto in Python).