2.13. Controllo del ciclo#

Due parole chiave modificano l’esecuzione di un ciclo:

  • break – esce immediatamente dal ciclo.

  • continue – salta il resto dell’iterazione corrente e passa alla successiva.

Entrambe si applicano al ciclo più interno in cui compaiono.

2.13.1. break#

Usa break per interrompere un ciclo non appena una condizione è soddisfatta. Il classico schema «cerca e fermati»:

found = None
for item in items:
    if matches(item):
        found = item
        break

if found is not None:
    print("found:", found)

In un ciclo while True:, break è il modo in cui il ciclo termina:

while True:
    line = next_line()
    if line == "quit":
        break
    process(line)

2.13.2. continue#

Usa continue per saltare il resto del corpo e passare all’iterazione successiva. Utile per filtrare gli elementi all’interno di un ciclo:

for n in numbers:
    if n < 0:
        continue            # skip negatives
    print(n)

Lo stesso effetto può essere scritto come un blocco if attorno al resto del corpo. continue a volte risulta più chiaro quando la condizione di salto è più semplice da esprimere in anticipo rispetto alla condizione di mantenimento.

All’interno di un ciclo, continue svolge lo stesso ruolo di un return anticipato in una funzione: salta i casi che non gestisci e mantiene il lavoro principale allineato all’indentazione esterna. Il ciclo filtra-ed-elabora è la forma canonica:

for item in items:
    if item is None:
        continue
    if not item.is_valid():
        continue
    process(item)

La riga indentata process(item) è il lavoro vero e proprio; ciascuna guardia sopra di essa specifica esattamente quali elementi vengono saltati.

2.13.3. else su un ciclo#

Sia for sia while accettano un blocco else opzionale. Viene eseguito quando il ciclo termina senza incontrare un break. L’uso più comune è un ciclo di ricerca che vuole un’alternativa nel caso in cui non venga trovato nulla:

for item in items:
    if matches(item):
        print("found:", item)
        break
else:
    print("no match")

Se viene attivato un break, il blocco else viene saltato. Leggi il costrutto come «for X in Y: …; oppure, se non siamo mai usciti, fai Z.»

2.13.4. Schemi di ciclo comuni#

Alcuni schemi ricorrono spesso negli script reali:

  • Polling – attendi che una condizione diventi vera prima di proseguire. Il corpo usa pass, l’istruzione no-op di Python; ogni blocco indentato deve contenere almeno un’istruzione, e pass è il modo per dire «non fare nulla qui»:

    while not ready():
        pass
    proceed()
    
  • Macchina a stati – un singolo ciclo while True: che sceglie cosa fare in base a una variabile di stato. Utile quando il lavoro si suddivide nettamente in poche fasi denominate:

    state = "header"
    for line in lines:
        if state == "header":
            if line.startswith("---"):
                state = "body"
        elif state == "body":
            print(line)
    
  • Accumulazione – costruisci un risultato mentre percorri una sequenza:

    total = 0
    for x in samples:
        total += x
    mean = total / len(samples)
    

    Molti cicli di accumulazione hanno un equivalente di una sola riga che usa una funzione built-in. Ricorri alla funzione built-in quando ne esiste una applicabile:

    • sum() – somma ogni elemento di un iterabile.

    • max() / min() – l’elemento più grande o più piccolo.

    • any()True se almeno un elemento è truthy.

    • all()True solo quando ogni elemento è truthy.

    • sorted() – una nuova lista con gli elementi ordinati.

    • len() – il numero di elementi (quando l’iterabile conosce la propria lunghezza).

    >>> samples = [3, 1, 4, 1, 5, 9, 2, 6]
    >>> sum(samples)
    31
    >>> sum(samples) / len(samples)        # mean
    3.875
    >>> max(samples)
    9
    >>> min(samples)
    1
    >>> sorted(samples)
    [1, 1, 2, 3, 4, 5, 6, 9]
    >>> any([False, False, True])
    True
    >>> all([True, True, False])
    False
    

    La versione built-in è più breve, più chiara e di solito più veloce rispetto a scrivere a mano lo stesso ciclo.