Un programma

Dove si scrive il primo programma.

Iniziare un programma

La possibilità di scrivere, rivedere, modificare, rieseguire linee di comandi permette di realizzare disegni anche piuttosto complicati utilizzando solo la shell di IDLE. Ma se vogliamo risolvere problemi più complessi dobbiamo realizzare tante funzioni e non è detto che riusciamo a farlo all’interno di un’unica sessione di lavoro. Dobbiamo scrivere un programma Python in una finestra di editor e salvarlo in un file in modo da poterlo riprendere, correggere, completare.

Un programma è un testo che contiene una sequenza di commenti, di funzioni e di comandi. Il programma deve essere scritto in un testo piano, senza nessun tipo di formattazione per cui non va usato, per scriverlo, un normale elaboratore di testi, ma un «editor» che permette di scrivere e di salvare esattamente e solo i caratteri immessi dalla tastiera.

Oltre alla shell, che abbiamo utilizzato finora, IDLE metta a disposizione anche un editor di testo e sarà quello che utilizzeremo. Per iniziare un nuovo programma, dal menu File scegliamo la voce New File o New Window e apparirà una nuova finestra completamente vuota con il cursore lampeggiante in alto a sinistra.

Prima ancora di incominciare a riempirla, pensiamo a un nome da dare al programma, il nome deve essere significativo per noi. Nel mio caso, dato che questo è il primo programma che ho scritto per il manuale l’ho chiamato: «man1.py».

Nota

L’estensione «.py» indica che questo file contiene un programma scritto in Python. Fino ad una certa versione, IDLE non aggiunge l’estensione al file, quindi bisogna ricordarsi di terminare sempre il nome del programma con le tre lettere: «.py» se vogliamo che il testo sia riconosciuto come un programma scritto in Python.

Pensato ad un nome adatto, salviamo il file prestando ben attenzione a dove viene salvato, in modo da riuscire a ritrovarlo in seguito: dal menu File scegliamo la voce Salva, spostiamoci nella cartella nella quale abbiamo deciso di mettere il programma, scriviamo il nome del programma e confermiamo con il tasto <Invio>.

I commenti

I comandi e le funzioni sono già stati visti dei capitoli precedenti. I commenti sono molto importanti per poter capire programmi scritti da altre persone ma anche programmi scritti da noi stessi, magari qualche tempo prima. Ci sono due tipi di commenti: commenti di linea e commenti su più linee. Il carattere cancelletto, #, indica l’inizio di un commento che si estende fino alla fine della riga. Quando l’interprete Python incontra il carattere # passa ad interpretare la riga seguente:

# questo è un commento

Se abbiamo bisogno di scrivere un commento che si estenda su più linee possiamo iniziare ogni linea con il carattere # oppure iniziare e terminare il commento con tre virgolette """ di seguito:

"""Questo è un

commento scritto su

più linee"""

Il primo mattone del programma

Rimbocchiamoci le maniche e iniziamo a scrivere il nostro primo programma.

Ogni programma deve essere ben commentato, in particolare deve avere un’intestazione che indichi l’interprete, il nome del file, l’autore, la data, il tipo di licenza e, ovviamente, un titolo.

In questo esempio ci poniamo l’obiettivo di far disegnare alla tartaruga un muro di mattoni quadrati. L’intestazione del programma potrebbe essere:

# man1.py
# 2 gennaio 2018
# Daniele Zambelli

"""
Il programma deve disegnare un muro di mattoni quadrati.
"""

Le prime tre righe danno alcune informazioni sul programma: nome del file, data di creazione, autore. Il commento scritto sotto forma di stringa, quello tra virgolette triple, si chiama docstring del programma: è un testo (una stringa) di documentazione che sintetizza ciò che fa, o deve fare, il programma stesso.

Scritta l’intestazione, se vogliamo, possiamo anche eseguire il programma. Possiamo farlo attraverso il menu:

Run - Run module

o premendo semplicemente il tasto:

<F5>

Per tutta risposta IDLE ci chiede se volgiamo salvare le modifiche apportate al programma. Noi, ovviamente, confermiamo.

Nota

dato che ogni volta che vogliamo eseguire il programma, vogliamo anche salvare le modifiche, possiamo andare su menu Option-Configure IDLE e nella scheda General selezionare No Prompt. D’ora in poi, dopo la pressione del tasto F5 non ci verrà più richiesta la conferma del salvataggio del file.

Premuto <F5>, se Python interpreterà correttamente il programma, non darà alcun messaggio di errore, ma, essendo composto solo da commenti non eseguirà assolutamente niente.

Incominciamo allora ad aggiungere istruzioni. Poiché vogliamo utilizzare la grafica della tartaruga, come primo comando dobbiamo caricare la libreria, creare un piano e creare una nuova tartaruga:

import pygraph.pyturtle as tg
tp = tg.TurtlePlane()
tina = tg.Turtle()

Ora, per costruire un muro di mattoni quadrati, abbiamo bisogno di una funzione che disegni quadrati:

def quadrato(lato):
    """Disegna un quadrato di dato lato."""
    for i in range(4)
        tina.forward(lato)
        tina.left(90)

Ormai siamo super esperti in quadrati… Ma questa volta aggiungiamo un commento come prima riga della funzione. Si chiama docstring e ogni funzione, oltre ad un nome significativo, dovrebbe averne una.

Ora dobbiamo eseguire il programma (Run - Run module o più velocemente tasto <F5>). A questo punto i casi sono due:

  1. Non succede assolutamente niente.
  2. Python scrive alcune strane righe nella shell di IDLE.

Nel primo caso, vuol dire che è andato tutto bene, Python non ha eseguito niente perché noi abbiamo definito una funzione, ma non abbiamo dato il comando di eseguirla e giustamente il computer non si prende la responsabilità di farlo di propria iniziativa.

Nel secondo caso, le strane scritte sono un messaggio di errore: Python non è riuscito a interpretare quello che abbiamo scritto e quindi non ha definito la procedura.

Tranello! Se la procedura è stata scritta esattamente come riportato sopra, Python ci risponde con:

File ".../sorgenti/graph/man1.py", line 10
  for i in range(4)
                   ^
SyntaxError: invalid syntax

Questo messaggio ci dà le seguenti informazioni:

  • in quale file si trova l’errore: …/sorgenti/graph/man1.py
  • la linea dove ha incontrato un errore: line 10,
  • il punto in cui l’interprete si è bloccato,
  • il tipo di errore: SyntaxError: invalid syntax

Già, ci siamo dimenticati i «:», correggiamola:

def quadrato(lato):
    """Disegna un quadrato di dato lato."""
    for i in range(4):
        tina.forward(lato)
        tina.left(90)

Ora dobbiamo eseguire di nuovo il programma tasto <F5> o menu: Run - Run module. Se tutto è andato bene, non dovrebbe succedere niente. Spostiamoci nella shell di IDLE e diamo il comando:

>>> quadrato(57)

Se non ci sono altri errori dovremmo ottenere un quadrato. Possiamo provare il funzionamento della funzione quadrato(lato) con diversi valori dell’argomento. È anche possibile aggiungere questo comando in fondo al programma. In questo modo, ogni volta che si esegue il programma verrà creata una tartaruga e disegnato un quadrato. Tutto il nostro programma è ora:

# man1.py
# 2 gennaio 2018
# Daniele Zambelli

"""
Il programma deve disegnare un muro di mattoni quadrati.
"""

# Lettura delle librerie
import pygraph.pyturtle as tg

# Definizione di funzioni

def quadrato(lato):
    """ Disegna un quadrato di dato lato """
    for cont in range(4):
        tina.forward(lato)
        tina.left(90)

# Programma principale
tp = tg.TurtlePlane()
tina = tg.Turtle()
quadrato(57)

# Rende attiva la finestra grafica
piano.mainloop()

L’ultima istruzione, come scritto nel commento, passa il comando alla finestra grafica rendendola attiva.

Eseguiamolo, se tutto funziona correttamente appare la finestra della grafica della tartaruga con dentro un quadrato. Bene, abbiamo scritto, salvato e provato il nostro primo programma funzionante, possiamo rilassarci un po” prima di procedere con il lavoro…

Nota

D’ora in poi non riporterò più l’intestazione e la docstring del programma.

Uno strato di mattoni

Disegnare un intero muro di quadrati può sembrare un’impresa piuttosto complicata. L’intero muro può essere pensato come composto da più file e ogni fila da più quadrati:

muro —(fatto da)—> fila —(fatta da)—> quadrato

La funzione che disegna un quadrato l’abbiamo realizzata, proviamo allora a realizzare la funziona che realizza una fila di quadrati tutti uguali. Questa funzione avrà bisogno di due informazioni: la dimensione dei quadrati e il numero di quadrati da mettere in una fila. Cioè vorremmo poter scrivere:

>>> fila(20, 15)

per ottenere una fila di 15 quadrati di lato 20. Per il numero di volte che abbiamo deciso, la funzione fila deve disegnare un quadrato e spostare la tartaruga avanti di un tratto uguale al lato del quadrato. La funzione potrebbe essere:

def fila(lato, numero):
    """Disegna una fila di mattoni."""
    for cont_col in range(numero):
        quadrato(lato)
        tina.forward(lato)

cont_col avremmo anche potuto chiamarla: contatore_delle_colonne oppure semplicemente: i o j. In generale dobbiamo dare alle variabili nomi significativi, ma non troppo lunghi. Aggiungiamo al programma la funzione fila(lato, numero) sotto alla funzione quadrato(lato), e, nel programma principale, al posto di disegnare un quadrato disegniamo una fila di quadrati:

# Lettura delle librerie
import pygraph.pyturtle as tg

# Definizione di funzioni

def quadrato(lato):
    """ Disegna un quadrato di dato lato """
    for cont in range(4):
        tina.forward(lato)
        tina.left(90)

def fila(lato, numero):
    """Disegna una fila di mattoni."""
    for cont_col in range(numero):
        quadrato(lato)
        tina.forward(lato)

# Programma principale
tp = tg.TurtlePlane()
tina = tg.Turtle()
fila(23, 7)

# Rende attiva la finestra grafica
piano.mainloop()

Eseguiamo il programma e proviamo la funzione modificando gli argomenti in modo da realizzare file più o meno lunghe di quadrati più o meno grandi.

La fila di quadrati viene disegnata, ma, la procedura fila, non è «trasparente»: oltre a disegnare una fila di quadretti, sposta la tartaruga senza rimetterla dove l’aveva trovata. È molto importante che ogni funzione faccia solo quello che dice di fare, senza effetti collaterali. Quindi la funzione fila deve preoccuparsi di rimettere a posto Tartaruga. Di quanto l’ha spostata? Per numero volte è andata avanti di lato passi, in totale numero*lato. Per rimettere a posto Tartaruga bisogna, finito il ciclo, farla indietreggiare della stessa quantità:

def fila(lato, numero):
    """Disegna una fila di mattoni."""
    for cont_col in range(numero):
        quadrato(lato)
        tina.forward(lato)
    tina.back(numero*lato)

La fila di quadrati che abbiamo ottenuto non richiama per niente dei mattoni, sono troppo appiccicati: un po” di malta tra uno e l’altro? Per distanziarli basta allungare lo spostamento dopo ogni quadrato e ovviamente anche al ritorno:

def fila(lato, numero):
    """Disegna una fila di mattoni."""
    for cont_col in range(numero):
        quadrato(lato)
        tina.forward(lato+5)
    tina.back(numero*(lato+5))

Funziona? Sì, ma non va bene. Esistono due tipi di errori quelli che bloccano il programma detti anche errori di sintassi e quelli che fanno fare al programma una cosa diversa da quella che volevamo, gli errori di semantica. Nel nostro caso la procedura funziona però non disegna quadrati staccati l’uno dall’altro, ma uniti da una linea non certo bella da vedere. Lo spostamento tra un quadrato e l’altro deve essere fatto senza lasciare segno:

def fila(lato, numero):
    """Disegna una fila di mattoni."""
    for cont_col in range(numero):
        quadrato(lato)
        tina.up()
        tina.forward(lato+5)
        tina.down()
    tina.up()
    tina.back(numero*(lato+5))
    tina.down()

L’intero muro

Possiamo essere soddisfatti del risultato ottenuto. Ora passiamo alla costruzione del muro. Cos’è un muro? È una pila di file di mattoni.

def muro():
    """Disegna un muro di quadrati."""
    for cont_rig in range(15):
        fila(20, 18)
        tina.up()
        tina.left(90)
        tina.forward(20+5)
        tina.right(90)
        tina.down()
    tina.up()
    tina.left(90)
    tina.forward(15*(20+5))
    tina.right(90)
    tina.down()

Aggiungiamo questa come terza funzione nel programma precedente e modifichiamo il programma principale sostituendo in modo che esegua: muro(). Il programma completo è:

# Lettura delle librerie
import pygraph.pyturtle as tg

# Definizione di funzioni

def quadrato(lato):
    """ Disegna un quadrato di dato lato """
    for cont in range(4):
        tina.forward(lato)
        tina.left(90)

def fila(lato, numero):
    """Disegna una fila di mattoni."""
    for cont_col in range(numero):
        quadrato(lato)
        tina.up()
        tina.forward(lato+5)
        tina.down()
    tina.up()
    tina.back(numero*(lato+5))
    tina.down()

def muro():
    """Disegna un muro di quadrati."""
    for cont_rig in range(15):
        fila(20, 18)
        tina.up()
        tina.left(90)
        tina.forward(20+5)
        tina.right(90)
        tina.down()
    tina.up()
    tina.left(90)
    tina.forward(15*(20+5))
    tina.right(90)
    tina.down()

# Programma principale
tp = tg.TurtlePlane()
tina = tg.Turtle()

tina.up()
tina.back(200)
tina.down()
muro()

# Rende attiva la finestra grafica
piano.mainloop()

Proviamola… funziona! … Ma…

Riassumendo

  • Un programma è un documento di testo che contiene istruzioni e funzioni.
  • Scritto un programma bisogna salvarlo: menu: File Save ed eseguirlo: menu: Run - Run module.
  • Ogni programma deve iniziare con dei commenti che forniscono alcune informazioni generali sul programma stesso: nome del file, data di creazione, autore, … e con una docstring che sintetizza ciò che fa, o deve fare, il programma stesso.
  • Le funzioni definite in un programma possono essere eseguite anche dall’ambiente shell IDLE.
  • Non è mai conveniente cercare di scrivere un intero programma e poi provarlo. Conviene, inizialmente, individuare obiettivi semplici, realizzarli e man mano completarlo provandone il funzionamento ad ogni aggiunta.