# Cicli e condizioni in Python: for, while, range, enumerate, break, if/elif e match/case

URL: https://skillaria.top/it/guides/python/cicli-python

I cicli in Python ripetono le azioni: for scorre gli elementi di una collezione o di un range(), mentre while continua finché la condizione è vera. Si può interrompere un ciclo con break, saltare un'iterazione con continue, numerare gli elementi con enumerate(). Le decisioni si prendono con if/elif/else, mentre la struttura match/case (da Python 3.10) serve a riconoscere i dati dalla loro forma.

I cicli in Python servono a ripetere un'azione: scorrere la lista della spesa, elaborare ogni riga di un file, chiedere all'utente un numero finché non ne inserisce uno corretto. Il linguaggio ha due cicli, `for` e `while`, e per prendere decisioni al loro interno si usano le condizioni `if/elif/else` e la struttura `match/case`. Vediamo ogni strumento con esempi pratici.

## Condizioni: if, elif, else

L'istruzione condizionale esegue un blocco di codice solo se l'espressione è vera. Il blocco si delimita con un rientro di 4 spazi: in Python non ci sono parentesi graffe, e un rientro sbagliato genera subito `IndentationError`.

```
spent = 4200
limit = 5000

if spent > limit:
    print("Limite superato")
elif spent > limit * 0.8:
    print("Resta meno del 20% del budget")
else:
    print("Tutto a posto")
```

I rami `elif` vengono controllati dall'alto verso il basso e si esegue solo il primo che corrisponde. Quindi le condizioni più restrittive vanno messe in alto: se la verifica `spent > limit * 0.8` fosse la prima, il messaggio sul superamento del limite non comparirebbe mai.

### Che cosa è considerato vero

Nella condizione non è obbligatorio scrivere un confronto. Sono considerati falsi `False`, `None`, lo zero (`0`, `0.0`) e le collezioni vuote: `""`, `[]`, `{}`. Tutto il resto è vero. Quindi la verifica «la lista non è vuota» si scrive in modo breve:

```
expenses = []
if not expenses:
    print("Nessuna spesa per ora")
```

Le condizioni si combinano con `and`, `or`, `not`, e un intervallo si verifica comodamente con un confronto a catena: `if 0 < amount <= 100_000:`. Per una scelta breve di valore esiste l'operatore ternario: `status = "alto" if spent > limit else "normale"`.

## Il ciclo for in Python: sintassi ed esempi

Il ciclo `for` in Python non è un contatore come in C, ma un'iterazione sugli elementi. Prende in sequenza ogni elemento di un oggetto iterabile: lista, stringa, dizionario, file, range. È l'equivalente del foreach di altri linguaggi: in Python è semplicemente il `for`.

```
expenses = [350, 1200, 89, 4500]
total = 0
for amount in expenses:
    total += amount
print(total)  # 6139
```

Sintassi del ciclo for: `for variabile in collezione:`, seguito dal blocco con rientro. Dopo il ciclo la variabile conserva l'ultimo valore: a volte è utile, ma nei programmi grandi non conviene affidarsi a questo comportamento.

### Ciclo su stringa, lista e dizionario

La stringa viene scorsa carattere per carattere, la lista elemento per elemento. Il ciclo su un dizionario scorre per impostazione predefinita le chiavi; per ottenere insieme chiave e valore si usa `.items()`:

```
by_category = {"cibo": 3200, "trasporti": 900, "cinema": 600}

for category, amount in by_category.items():
    print(f"{category}: {amount} €")
```

Per i soli valori c'è `.values()`. Non si può cambiare la dimensione del dizionario durante il ciclo: si ottiene `RuntimeError: dictionary changed size during iteration`. Se bisogna rimuovere elementi, scorrete una copia: `for key in list(d):`.

## La funzione range: ciclo sui numeri

Quando serve scorrere dei numeri, si usa `range()`. Non crea una lista in memoria, ma restituisce i numeri uno alla volta, quindi `range(10**9)` funziona istantaneamente.

| Chiamata | Numeri |
| --- | --- |

| `range(5)` | 0, 1, 2, 3, 4 |

| `range(2, 6)` | 2, 3, 4, 5 |

| `range(0, 10, 3)` | 0, 3, 6, 9 |

| `range(5, 0, -1)` | 5, 4, 3, 2, 1 |

La regola principale: il limite destro non è incluso. `range(1, 10)` termina con 9 — è una causa frequente dell'errore «di uno». Il passo può essere negativo, ma non può essere zero.

```
for i in range(1, 4):
    print(f"Giorno {i}")
# Giorno 1
# Giorno 2
# Giorno 3
```

## enumerate: contatore nel ciclo

I principianti scrivono spesso `for i in range(len(items))` per conoscere il numero dell'elemento. Funziona, ma si legge peggio. La funzione `enumerate()` restituisce coppie «numero, elemento», e il parametro `start` stabilisce da quale numero partire:

```
items = ["caffè", "taxi", "pranzo"]
for n, item in enumerate(items, start=1):
    print(n, item)
# 1 caffè
# 2 taxi
# 3 pranzo
```

Per scorrere in parallelo due liste c'è `zip()`: `for name, price in zip(names, prices):`. Si ferma alla lista più corta; dalla versione 3.10 si può passare `strict=True`, e in quel caso lunghezze diverse generano un errore.

## Il ciclo while in Python

Il ciclo `while` ripete il blocco finché la condizione è vera. Si sceglie quando il numero di ripetizioni non è noto in anticipo: si attende un input corretto, si leggono dati fino alla fine, si ripete una richiesta fino al successo.

```
balance = 10_000
month = 0
while balance > 0:
    balance -= 2_700
    month += 1
print(f"I soldi bastano per {month} mesi")  # 4
```

Il pericolo principale è dimenticare di modificare la variabile della condizione: il ciclo non finirebbe mai. Se il programma sembra bloccato, premete Ctrl+C: Python interrompe l'esecuzione con `KeyboardInterrupt`.

### Ciclo infinito e il «do while»

A volte il ciclo infinito in Python si scrive di proposito: `while True:` con l'uscita tramite `break`. Lo stesso schema sostituisce il ciclo con controllo finale: in Python non esiste il costrutto `do while`, e lo si imita così — il corpo viene eseguito almeno una volta e la verifica sta alla fine.

```
while True:
    raw = input("Importo: ")
    if raw.isdigit():
        amount = int(raw)
        break
    print("Inserite un numero intero")
```

Un ciclo for infinito è raro: succede solo se si scorre un iteratore senza fine, per esempio `itertools.count()`.

## break e continue: uscita dal ciclo e salto dell'iterazione

`break` interrompe subito il ciclo e l'esecuzione prosegue con il codice che segue. `continue` salta il resto dell'iterazione corrente e passa alla successiva.

```
expenses = [350, -10, 1200, 0, 99_999, 89]

for amount in expenses:
    if amount  50_000:
        print("Importo sospetto, stop")
        break             # esce dal ciclo
    print(amount)
```

Verranno stampati 350 e 1200, poi il messaggio: il ciclo non arriva fino a 89. Entrambe le istruzioni agiscono solo sul ciclo più vicino in cui si trovano.

### else nel ciclo

`for` e `while` hanno un ramo `else` insolito: viene eseguito se il ciclo è terminato da solo, senza `break`. È comodo per le ricerche:

```
for amount in expenses:
    if amount > 50_000:
        print("Trovata una spesa grande")
        break
else:
    print("Non ci sono spese grandi")
```

## Cicli annidati

Un ciclo dentro un altro esegue quello interno per intero a ogni iterazione di quello esterno. Così si scorrono tabelle, matrici, si generano coppie.

```
for row in range(1, 4):
    for col in range(1, 4):
        print(row * col, end="\t")
    print()
```

Due cose da ricordare. Primo: la complessità cresce in fretta, e due cicli annidati su 10 000 elementi significano 100 milioni di operazioni. Secondo: `break` esce solo dal ciclo interno. Per interrompere entrambi conviene mettere i cicli in una funzione e usare `return`: è più pulito dei flag.

## L'istruzione match/case

La lunga catena `if cmd == ... elif ...` dalla versione 3.10 si può sostituire con `match` (PEP 634). Non è un semplice switch: confronta il valore con un modello basato sulla forma dei dati e separa subito le parti in variabili.

```
def parse(text):
    match text.split():
        case ["add", item, amount]:
            return f"Aggiungi {item}: {amount}"
        case ["list"] | ["ls"]:
            return "Mostra le spese"
        case ["quit"]:
            return "Uscita"
        case _:
            return "Comando sconosciuto"

print(parse("add Caffè 250"))  # Aggiungi Caffè: 250
print(parse("add Caffè"))      # Comando sconosciuto
```

Il modello-lista `["add", item, amount]` corrisponde solo a una lista di esattamente tre elementi, il primo dei quali è `"add"`. Quindi un comando senza importo finisce nel ramo `_`, che cattura tutto il resto. Il simbolo `|` unisce le varianti.

### Dizionari, tipi e condizione di guardia

Il modello-dizionario controlla solo le chiavi elencate, e quelle extra vengono ignorate. La scrittura `int(a)` verifica il tipo e cattura il valore, mentre un `if` dopo il modello aggiunge una condizione ulteriore (guard):

```
match event:
    case {"type": "expense", "amount": int(a)} if a > 10_000:
        print("Spesa grande", a)
    case {"type": "expense", "amount": int(a)}:
        print("Spesa", a)
```

### La trappola principale di match

Un nome semplice in `case` è una cattura, non un confronto con una variabile. `case limit:` corrisponde a qualsiasi valore e lo scrive in `limit`. Per confrontare con costanti bisogna usare un nome puntato, per esempio `case Color.RED:`, oppure dei letterali.

La sintassi di match dalla 3.10 è rimasta quasi invariata. Nella Python 3.15 è stata eliminata una piccola asimmetria: nei modelli letterali prima era ammesso il meno davanti a un numero, ora si può scrivere anche `case +1:`. Nelle versioni più vecchie questo codice darà un errore di sintassi.

## Errori tipici nei cicli

- **Modifica della lista durante il ciclo.** Rimuovere elementi dentro un `for` ne salta alcuni. Meglio costruire una nuova lista: `clean = [x for x in items if x > 0]`.
- **Limite di range.** `range(1, n)` non include `n`.
- **Dimenticare di modificare la condizione del while** — ciclo infinito.
- **Unire stringhe nel ciclo con +=**: con grandi volumi è più lento di `"".join(parts)`.
- **Assegnazione al posto del confronto**: `if x = 5` è un errore di sintassi; il confronto si scrive con `==`.

## Esercizi sui cicli

1. Calcolate la somma e la media di una lista di spese, saltando i valori negativi.
2. Stampate la tabellina da 1 a 9 con cicli annidati.
3. Chiedete all'utente dei numeri finché non inserisce una riga vuota, poi stampate il massimo.
4. Trovate il primo numero maggiore di 1000 in una lista e segnalate se non c'è (con `for ... else`).
5. Analizzate i comandi `add`, `del`, `list` con `match`.

## Conclusioni

I cicli di Python si riducono a due costrutti: `for` scorre gli elementi di una collezione o di `range()`, `while` lavora finché la condizione è vera. `break` e `continue` governano il percorso del ciclo, `enumerate()` e `zip()` eliminano i contatori manuali, mentre `if/elif/else` e `match/case` si occupano delle decisioni. Tutti questi strumenti sono trattati in pratica sull'esempio del tracker delle spese nella lezione del corso dedicata a Python.

## FAQ

**In che cosa differiscono for e while in Python?**

for scorre una sequenza già pronta e sa da solo quando fermarsi, mentre while si ripete finché la condizione è vera. Se il numero di ripetizioni è noto o c'è una collezione, usate for; se aspettate un evento, usate while.

**Come scorrere un ciclo al contrario?**

Usate reversed(items) per una collezione oppure range(n - 1, -1, -1) per i numeri. La funzione reversed non copia la lista, ma la scorre partendo dalla fine.

**Python ha lo switch?**

Non esiste uno switch separato: il suo ruolo è svolto dalla catena if/elif e dall'istruzione match/case, comparsa in Python 3.10. match sa fare di più: scompone liste e dizionari in base alla forma e cattura i valori.

**È più veloce un ciclo o una list comprehension?**

La list comprehension del tipo [x * 2 for x in items] di solito è un po' più veloce del ciclo equivalente con append e più corta. Per logiche complesse con più condizioni il ciclo classico è più leggibile.

**Come uscire da due cicli annidati contemporaneamente?**

break interrompe solo il ciclo interno. La soluzione più semplice è spostare i cicli in una funzione e uscire con return.


---
Source: Skillaria.Top (https://skillaria.top)
