Cicli for e range — ripetere un numero noto di volte
Quando sai quante volte ripetere, il ciclo for è la scelta giusta. Le tre forme di range, perché la fine è esclusa e come scegliere tra for e while.
Come vuoi imparare?
Il problema che stiamo risolvendo
Nel capitolo precedente sommare da 1 a 5 richiedeva quattro righe, due delle quali servivano solo a tenere il conto — un valore iniziale e un incremento. Dimentica l'incremento e ottieni un ciclo infinito.
Ma nota una cosa su questo tipo di lavoro: sapevamo in anticipo quante volte sarebbe stato eseguito. Cinque. Quando è così, non c'è motivo di tenere il conto a mano — puoi affidarlo a Python.
È esattamente quello che fa un ciclo for. E poiché il conteggio non è più nelle tue mani, un ciclo for su un range non può diventare infinito da solo — il numero di giri è fissato nel momento in cui il ciclo inizia. È questo il suo vantaggio più grande. (C'è un'eccezione: se scorri una lista e aggiungi elementi alla lista stessa dentro il ciclo, il ciclo non finisce mai. Le liste arrivano nel prossimo capitolo.)
Alla fine di questo capitolo sarai in grado di
- Eseguire codice un numero noto di volte con un ciclo
for - Usare tutte e tre le forme di
range() - Spiegare perché
range(1, 5)produce quattro numeri, non cinque - Scorrere i caratteri di una stringa
- Scegliere tra
forewhileper un dato compito
Prerequisiti: Cicli while — ripetere finché una condizione è vera.
La forma più semplice
for number in range(5):
print(number)0
1
2
3
4Tre righe di lavoro in una sola, senza nessun contatore da gestire. Leggilo così: "per ciascuno dei numeri che `range(5)` produce, esegui il blocco una volta — e ogni volta metti quel numero in `number`."
Due cose saltano subito all'occhio:
Parte da zero, e il 5 non compare mai — cinque numeri in tutto, cioè da 0 a 4. È la stessa regola che Python applica ovunque: come l'indice finale è escluso in una slice, lo è anche in un range.
Il nome number lo scegli tu. for i in range(5) va altrettanto bene, e i è il nome convenzionale per un contatore. Ma quando il numero ha un significato, dagli un nome che ne esprima il significato — for student_number in range(30) si capisce da solo.
Le tre forme di range()
print("--- range(5) ---")
for i in range(5):
print(i, end=" ")
print()
print("--- range(2, 6) ---")
for i in range(2, 6):
print(i, end=" ")
print()
print("--- range(0, 10, 3) ---")
for i in range(0, 10, 3):
print(i, end=" ")
print()
print("--- range(5, 0, -1) ---")
for i in range(5, 0, -1):
print(i, end=" ")
print()--- 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 1Le regole:
range(stop)— parte da0, si ferma prima distoprange(start, stop)— parte dastart, si ferma prima distoprange(start, stop, step)— avanza distepogni volta; unstepnegativo conta all'indietro
Controlla gli ultimi due. range(0, 10, 3) dà 0 3 6 9 — il successivo sarebbe 12, che supera 10, quindi si ferma. E range(5, 0, -1) dà 5 4 3 2 1 — lo 0 non compare mai, perché anche qui la fine è esclusa.
Perché la fine è esclusa? Perché rende facili i conti. Quanti numeri ci sono inrange(0, 5)?5 - 0, cioè cinque. Inrange(3, 8)?8 - 3, cinque. Sottrai e hai il conteggio, senza doversi chiedere se aggiungere uno. E due range messi uno dopo l'altro —range(0, 5)erange(5, 10)— non perdono nulla e non ripetono nulla.
Quando ti servono da uno a dieci
Questo errore capita spesso abbastanza da meritare una sezione tutta sua:
print("Wrong — stops at 9:")
for i in range(1, 10):
print(i, end=" ")
print()
print("Right — includes 10:")
for i in range(1, 11):
print(i, end=" ")
print()Wrong — stops at 9:
1 2 3 4 5 6 7 8 9
Right — includes 10:
1 2 3 4 5 6 7 8 9 10La regola in una riga: scrivi come stop un numero più grande di uno rispetto all'ultimo che vuoi.
Accumulare — ora in modo più semplice
total = 0
for number in range(1, 6):
total = total + number
print("Sum of 1 to 5:", total)Sum of 1 to 5: 15Confrontalo con la versione while dello stesso compito: nessun contatore da creare, nessuno da incrementare, nessun rischio di ciclo infinito. Solo l'accumulatore deve ancora partire fuori dal ciclo, esattamente come prima.
Scorrere una stringa
for non scorre solo i numeri — scorre anche una stringa, carattere per carattere:
word = "Python"
for letter in word:
print(letter, end="-")
print()
vowel_count = 0
for letter in "programming":
if letter in "aeiou":
vowel_count = vowel_count + 1
print("Vowels:", vowel_count)P-y-t-h-o-n-
Vowels: 3Qui non serve nessun range: for letter in word scorre direttamente i caratteri. È più semplice dell'aritmetica sugli indici, e non c'è nessun IndexError da temere.
Quando ti servono sia l'indice sia il carattere, c'è enumerate(); arriva nel capitolo sulle liste.
break e continue funzionano anche qui
Esattamente come nel while:
for number in range(1, 20):
if number % 7 == 0:
print("First multiple of 7:", number)
breakFirst multiple of 7: 7Scegliere tra for e while
Fatti una sola domanda: il numero di ripetizioni è noto prima che il ciclo inizi?
Se sì, for:
- Eseguire cinque volte
- Andare da 1 a 100
- Esaminare ogni carattere di una parola
- Fare qualcosa con ogni elemento di una lista
Se no, while:
- Continuare a chiedere finché l'input non è valido
- Eseguire finché la persona non scrive
quit - Leggere finché nel file ci sono righe
Nel dubbio, scegli for. Il motivo è semplice: un ciclo for su un range o su una stringa fissa è garantito che finisca, mentre un ciclo while non lo è. Quando entrambi andrebbero bene, la scelta migliore è quella che permette di fare meno errori.
Un esempio completo
multiplication.py:
# Print a multiplication table, then a small summary
number = int(input("Which table? "))
upto = int(input("Up to? "))
print()
print(f"--- Table of {number} ---")
total = 0
for i in range(1, upto + 1):
result = number * i
total = total + result
print(f"{number} x {i:2} = {result:4}")
print()
print(f"Rows : {upto}")
print(f"Sum : {total}")
print(f"Average : {total / upto:.2f}")Which table? 7
Up to? 5
--- Table of 7 ---
7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
Rows : 5
Sum : 105
Average : 21.00Tre cose da notare. Primo, range(1, upto + 1) — per arrivare a upto è stato necessario scrivere uno in più. Secondo, {i:2} e {result:4} — dentro una f-string puoi indicare quanta larghezza deve occupare un numero, e così le colonne restano allineate. Terzo, total parte fuori dal ciclo e cresce dentro — lo stesso accumulatore di prima.
E chiediti una cosa: che cosa succede se la persona risponde 0 alla domanda Up to?. Il range(1, 1) non produce alcun numero, quindi il ciclo non gira mai — e poi total / upto divide per zero. È la stessa lezione del capitolo precedente: prima di usare ciò che un ciclo ha accumulato, verifica che abbia accumulato davvero qualcosa.
Quando qualcosa va storto
Manca l'ultimo numero range(1, 10) finisce a 9. Aggiungi uno allo stop: range(1, 11).
TypeError: 'float' object cannot be interpreted as an integer range() accetta solo numeri interi (int). range(2.5) o range(1, n / 2) non funzionano — converti con int(), oppure dividi con //.
SyntaxError: expected ':' Manca i due punti alla fine della riga for.
IndentationError: expected an indented block after 'for' statement La riga dentro il ciclo non è indentata.
Il ciclo non è mai stato eseguito Il range è vuoto. range(5, 0) non produce nulla — per contare all'indietro ti serve il terzo argomento: range(5, 0, -1).
Il totale è 0 dopo il ciclo La riga total = 0 è finita dentro il ciclo, quindi si azzera a ogni giro. Deve stare fuori.
Una variabile creata nel ciclo serve anche fuori, ma compare un NameError Il range era vuoto, quindi il ciclo non è mai stato eseguito e la variabile non è mai stata creata. Assegnale un valore iniziale prima del ciclo.
Passo 4 di 6 — Prevedi
Verifica cosa hai capito
Che cosa stampa questo ciclo?
for i in range(1, 5):
print(i, end=" ")- A1 2 3 4 5
- B1 2 3
- C0 1 2 3 4
- D1 2 3 4
Il terzo argomento imposta il passo. Qual è l'output?
for i in range(0, 10, 3):
print(i, end=" ")- A3 6 9
- B0 3 6 9
- C0 1 2 3 4 5 6 7 8 9
- D0 3 6 9 12
L'intento era la somma da 1 a 10, cioè 55. Invece stampa 45. Perché?
total = 0
for number in range(1, 10):
total = total + number
print("Sum of 1 to 10:", total)- A`total` è inizializzato fuori dal ciclo, mentre dovrebbe stare dentro
- BUsare un ciclo `while` invece di `for` darebbe la risposta giusta
- CDovrebbe essere `total + i` invece di `total + number`
- D`range(1, 10)` finisce a `9` e lascia fuori `10` — serve `range(1, 11)`
Per rispondere serve un account
Accedi per verificare le tue risposte
Le domande sono qui sopra, e ragionarci a mente è la parte che conta. Accedi per vedere le risposte, le spiegazioni e i suggerimenti a tre livelli.
Tocca a te
Scrivi un file chiamato stars.py che riceve un numero e stampa un triangolo. Con 5:
*
**
***
****
*****Poi aggiungi queste tre cose:
- Stampa in fondo il numero totale di stelle (15 per un input di 5)
- Stampa anche il triangolo capovolto — cinque in alto, uno in basso
- Stampa una versione che salta le righe pari (usa
continue)
C'è un modo semplice per verificare il primo punto — calcola a mano la somma da 1 a 5 e controlla che il tuo programma sia d'accordo. E ti ricordi di "*" * i? Per costruire una riga di stelle non serve un ciclo dentro il ciclo.
Passo 6 di 6
Sfida — il quiz del capitolo
Dieci domande dalla più facile alla più difficile. Le ultime sono difficili di proposito.
Accedi per fare il quiz