Software in pratica

 ☗   ◀   ☰   ▶ 

RIPETIZIONI

Per poter ripetere automaticamente un certo numero di volte una o più istruzioni (o anche l'intero programma) è indispensabile un'istruzione in grado di creare i cosiddetti loop, cicli o anelli, che vengono appunto utilizzati per ripetere le istruzioni inserite al loro interno.

Vediamo come è formato un loop, il suo inizio è composto dall'istruzione while, seguita, come per if, da una condizione e dai due punti. Sotto al while, indentate di 4 spazi, si scrivono le istruzioni da ripetere interne al loop. Queste istruzioni vengono ripetute continuamente fintanto che la condizione specificata continua a risultare vera. La struttura generale del loop è pertanto:

while condizione:
    istruzione 1
    istruzione 2
    istruzione n
Rappresentazione grafica:



Vediamo subito un esempio che mostra come creare un loop con un numero preciso di ripetizioni (iterazioni):

 
i = 1
while i <= 10:
    print("SERVI DELLA PLEBE")
    i = i + 1


Questo programma stampa per 10 volte la scritta "SERVI DELLA PLEBE" (i computer sono servi della plebe). La variabile i è usata come contatore di ciclo (o variabile di controllo del ciclo) e viene incrementata ad ogni iterazione, quando raggiunge il valore 11 il ciclo termina e il programma prosegue con le istruzioni successive non indentate.

Notare che se la condizione controllata dal ciclo risulta falsa già dall'inizio le istruzioni all'interno del ciclo non vengono eseguite neppure una volta.


NIDIFICAZIONE

Come per le strutture condizionali if, anche le strutture iterative while possono essere nidificate a piacere, e di fatto ogni programma è sempre formato da blocchi di istruzioni sequenziali "incastonati" in strutture condizionali e iterative che ne stabiliscono l'ordine di esecuzione (flusso).

Questo tipo di organizzazione dei programmi, che fa uso di sole strutture sequenziali, condizionali e iterative (oltre alla scrittura indentata che in Python è una regola sintattica obbligatoria ma in altri linguaggi è facoltativa), fa parte di un insieme di regole di buona programmazione che prende il nome di programmazione strutturata, e permette non solo di ottenere programmi con meno errori, ma anche di scrivere listati (listing) facilmente comprensibili sia ad altre persone sia a voi stessi quando li rileggerete dopo molto tempo.

A proposito dei loop nei loop a cui ho accennato, se i cicli che realizzate fanno uso nella condizione di una variabile di controllo del ciclo, bisogna fare attenzione a non modificare nei cicli interni la stessa variabile usata dal ciclo esterno, ad esempio provate a far girare questo programma:

#---------- PROGRAMMA CICLI (ERRATO)

h = 1
while h <= 10:
    print("PASSAGGIO ESTERNO NUMERO", h)
    h = 1
    while h <= 3:
        print("   PASSAGGIO INTERNO NUMERO", h)
        h = h + 1
    h = h + 1

Idealmente dovrebbe essere formato da un ciclo di 10 ripetizioni che contiene un ciclo di 3 ripetizioni (ripetuto appunto 10 volte), però l'esecuzione non termina mai (e sarete costretti ad interrompere il programma con CONTROL + C), infatti il ciclo interno modifica il valore della variabile h usata anche da quello esterno, e la condizione di termine di quello esterno non arriva mai. E' un esempio di side effect (effetto collaterale) dovuto alla modifica involontaria di variabili che non dovrebbero essere modificate in altri punti se non dove è richiesto farlo.

Invece se ogni ciclo usa una propria variabile di controllo indipendente, tutto funziona regolarmente, come nell'esempio seguente, dove facciamo anche una parametrizzazione del funzionamento specificando con due variabili il numero di cicli esterni e interni che devono essere effettuati.

Queste variabili sono per convenzione scritte in maiuscolo per evidenziare che verranno usate come costanti, per rappresentare dei valori in diversi punti del programma senza cospargerlo di "numeri magici", di cui non solo si dimenticherebbe facilmente il significato, ma, volendoli modificare, si rischierebbe di dimenticarne qualcuno ottenendo un programma malfunzionante in cui sarebbe molto difficile scovare l'errore.

#---------- PROGRAMMA CICLI (CORRETTO)

C_EST = 3  # numero cicli esterni
C_INT = 2  # numero cicli interni
h = 1
while h <= C_EST:
    print("PASSAGGIO ESTERNO NUMERO", h)
    i = 1
    while i <= C_INT:
        print("   PASSAGGIO INTERNO NUMERO", i)
        if  h == C_EST  and  i == C_INT:
            print("   EHI! QUESTO E' L'ULTIMO!!!")
        i = i + 1
    h = h + 1
Risultato:
PASSAGGIO ESTERNO NUMERO 1
   PASSAGGIO INTERNO NUMERO 1
   PASSAGGIO INTERNO NUMERO 2
PASSAGGIO ESTERNO NUMERO 2
   PASSAGGIO INTERNO NUMERO 1
   PASSAGGIO INTERNO NUMERO 2
PASSAGGIO ESTERNO NUMERO 3
   PASSAGGIO INTERNO NUMERO 1
   PASSAGGIO INTERNO NUMERO 2
   EHI! QUESTO E' L'ULTIMO!!!



CICLI FLOATING POINT

Premetto che non è una buona pratica di programmazione, ma con una piccola attenzione potete anche creare cicli con numeri con la virgola, ad esempio per far assumere alla variabile di controllo tutti i valori compresi tra 5.0 e 6.0 a passi di 0.1

c = 5.0
while round(c, 1) <= round(6.0, 1):
    print(round(c,1))
    c = c + 0.1

Questo programmino stampa esattamente 11 righe:

5.0
5.1
5.2
5.3
5.4
5.5
5.6
5.7
5.8
5.9
6.0

La piccola attenzione è l'uso della funzione round, in questo caso a un decimale (che arrotonda appunto a una cifra decimale), sul valore di c. Questo è necessario perché i numeri floating point non possono essere rappresentati con precisione assoluta, e quindi ripetuti incrementi di 0.1 accumulano un piccolo errore ad ogni ciclo, la cosa non causa normalmente alcun problema (Python ha una precisione di 16 cifre, almeno pari se non superiore a quella di una comune calcolatrice scientifica), ma in un confronto di uguaglianza questo piccolo errore ha la sua importanza dato che 50.000000000000441 risulterebbe diverso da 50.0



TRUE E BREAK

Spesso è utile creare un ciclo senza fine, da cui uscire con un' apposita istruzione di terminazione solo al verificarsi di una certa condizione. Nel prossimo esempio il programma iniza con un ciclo while senza fine, che ha come condizione il valore True che rappresenta una condizione sempre vera. L'unico modo per uscire da un ciclo come questo e' usare l'istruzione break all'interno di esso. Quando viene incontrata una break l'esecuzione del ciclo termina immediatamente, e il programma prosegue con le righe successive che non fanno parte del blocco di istruzioni del ciclo stesso:

while True:
    b = int(input("QUANTO TI PIACE PYTHON (DA 1 A 10) ?"))
    if b <= 10:
        break
    print("GRAZIE MA E' TROPPO")
while b > 0:
    print("W PYTHON")
    b = b - 1
Risultato:
QUANTO TI PIACE PYTHON (DA 1 A 10) ?12
GRAZIE MA E' TROPPO
QUANTO TI PIACE PYTHON (DA 1 A 10) ?8
W PYTHON
W PYTHON
W PYTHON
W PYTHON
W PYTHON
W PYTHON
W PYTHON
W PYTHON


Nel primo ciclo viene chiesto un valore compreso tra 1 e 10, se si immette un valore superiore a 10 appare la scritta "GRAZIE MA E' TROPPO" e viene chiesta di nuovo l'immissione. Altrimenti il ciclo termina e inizia il secondo, che stampa per b volte la scritta inneggiante a Python.

Cercate di fare buon uso dei loop e sforzatevi di inventare qualsiasi cosa esca dalla vostra fulgida mente, ma soprattutto cercate di seguire passo passo le singole righe di programma immedesimandovi nel computer che le deve eseguire, e cercate di capire cosa deve accadere in ogni situazione verificandolo in pratica.

 ☗   ◀   ☰   ▶