9: ALTRE ISTRUZIONI PER IL CONTROLLO DI FLUSSO

L'ISTRUZIONE break

Abbiamo visto che in un while Python esegue il ciclo ed ogni volta che giunge alla fine ricontrolla la condizione di controllo ed eventualmente esce dal ciclo. A volte la condizione per uscire dal while risulta troppo complicata, altre volte sarebbe preferibile uscire dal ciclo non alla fine di esso ma ad una linea intermedia. Questo è possibile mediante l'istruzione break.

Quando, durante un ciclo, Python incontra l'istruzione break tutta le linee dal break fino alla fine del ciclo vengono saltate ed il programma esce dal ciclo continuando con la prima istruzione successiva.

Il break si usa spesso quando dobbiamo fare una ricerca su un insieme di elementi. Supponiamo di avere un insieme di tante scatole, una delle quali contiene 100 euro. Potenzialmente dobbiamo esaminarle tutte: apriamo la prima, poi la seconda ... e quando troviamo la scatola giusta smettiamo perchè non abbiamo bisogno di esaminare le rimanenti. Ecco un esempio.

NUOVO PROGRAMMA: divisibilita.py

Questo programma cerca un divisore di un numero intero immesso dall'utente. Per prima cosa chiede all'utente di inserire il numero n, poi entra in un ciclo while che usa un contatore k. Partentdo da 2, il programma controlla (con l'operatore %) il resto di tutte le divisioni n : k. Se una di queste da resto 0 n è divisibile per k ed il programma esce dal ciclo con il break. Se invece non trova divisori esce (con la condizione del while) quando k è maggiore di n // 2 (se k è maggiore della metà di n la divisione darà sicuramente 1 con il resto).


n = int (input("Scrivi un numero "))    # controlliamo se questo numero è primo
k = 2                                   # contatore: parte da 2 ...
while k <= n // 2:                      # ... e arriva a n//2
    if n % k == 0:                      # se questo e' vero, n e' divisibile per k
        print(n, "e' divisibile per", k)
        break                           # trovato un divisore, usciamo dal ciclo
    k += 1                              # altrimenti incrementiamo il contatore

A volte, alla fine del ciclo, è necessario che il programma "sappia" se si è usciti a causa di un break oppure perchè la condizione di controllo è risultata falsa. Per questo motivo è possibile inserire subito dopo il while (allo stesso livello di indentazione) un'istruzione else: questa viene eseguita se la condizione è falsa (e quindi si è usciti dal ciclo non a causa del break) mentre viene saltata se si è usciti con il break.

ESERCIZIO 9.1: Modificate il programma in modo che se alla fine non si è trovato un divisore stampi "xxx e' un numero primo". (Basta aggiungere alla fine un'istruzione else, indentata allo stesso livello del while, che verrà eseguita solo se il ciclo non è uscito a causa del break)
SOLUZIONI

Attenzione! E' sempre possibile inserire un else alla fine del while, ma questo non ha nessuna utilità se non c'è un break all'interno, in quanto l' else verrebbe eseguito comunque alla fine del ciclo (perchè la condizione è diventata falsa). Verrebbe addirittura eseguito anche se non si entrasse per niente nel ciclo.

NUOVO PROGRAMMA: prova_while_else.py

a = 0
while a < 10:
    print ("a =", a)
    a = a + 1
else:               #l'else viene SEMPRE eseguito
    print ("Ho eseguito l'else")

Modificare il programma precedente ponendo nella prima riga a = 1000. Cosa succede?

Una soluzione drastica che si adotta qualche volta quando le condizioni di uscita sono molto complicate è questa (aggiungete queste righe in coda al programma):


a = 0
while True:         #questa e' sempre vera! qui non si esce mai!
                    #a volte si usa anche while 1:
    print("Sto facendo calcoli mooooolto complicati")
    if a == 10:
        break       #in realta' si esce dal ciclo qui
    a += 1

L'ISTRUZIONE continue

Questa istruzione provoca immediatamente la prossima iterazione: si salta tutta la parte dal continue alla fine del ciclo. E' un'istruzione in effetti non indispensabile (si potrebbe ottenere lo stesso effetto con un if o un else), ma che permette spesso di rendere più leggibile il programma. Usarla o no è questione di gusti del programmatore: tipicamente si usa se vogliamo saltare qualche iterazione nel ciclo.

NUOVO PROGRAMMA: prova_continue.py

Questo programma scrive i quadrati e i cubi dei numeri da 1 a 100, meno un numero scelto da noi:


salta = int(input("Che numero devo saltare? "))
i = 0
while i < 100:
    i += 1
    if i == salta:
        continue
    print("i =", i)
    print("Il quadrato di i e'", i ** 2)
    print("Il cubo di i e'", i ** 3)
print ("Fine")

In questo caso è evidente che potremmo ottenere lo stesso comportamento con un else, ma supponiamo che il ciclo while sia composto di un gran numero di linee: dovremmo indentarle tutte due volte. Così il programma è più semplice da scrivere.

Domanda: perchè ho incrementato il contatore all'inizio? Cosa succederebbe se lo incrementassi alla fine del ciclo come ho sempre fatto finora?

NUOVO PROGRAMMA risposte.py

Un grande problema nei programmi che richiedono interattività è il controllo dell'input dell'utente. Consideriamo ad esempio questo frammento di codice:


risp = input("Vuoi la pizza o la pasta?")
if risp == "pizza":
    print ("Hai ordinato la pizza")
else:
    print ("Hai ordinato la pasta")

Qui il controllo è molto debole perchè il programma assume che voi scriviate "pizza" o "pasta". Cosa succederebbe se all'input voi rispondeste "qwertyuiop"? (provate a pensarci)...

Vediamo ora un programma un po' più sofisticato che ci chiede di rispondere "s" o "n" e continua a ripetere la domanda se scriviamo qualcosa di diverso: cercate di capire come ho usato le varie tecniche descritte in questa lezione:


# non c'e' bisogno di inizializzazione in quanto l'espressione di controllo non contiene variabili

while True:
    risp = input("Vuoi una tazzina di caffe'? (s/n) ")
    if risp == "s" or risp == "n":
        break
    print("Input non valido")
print ("Ciao!")

Il ciclo viene sempre eseguito (while True:). Si esce solo con il break quando la risposta è "s" o "n", altrimenti viene stampato "Input non valido" ed il ciclo ricomincia.

ESERCIZIO 9.2: Continuare il programma con un'altra domanda: Scrivi un numero da 3 a 15. Usare una costruzione simile a questa per controllare che l'input dell'utente sia effettivamente un numero nell'intervallo indicato.
SOLUZIONI

Attenzione! Questo programma dovrà comunque assumere che il nostro input sia un numero. Se immettessimo una stringa come xyzw andrà in crash con un ValueError. Per controllare queste situazioni servono istruzioni che ancora non conosciamo.

Fine della lezione