12. Iterazione con i cicli for e range()
Nel Capitolo 11, abbiamo imparato i cicli while, che ripetono azioni finché una condizione rimane vera. Sebbene i cicli while siano potenti e flessibili, richiedono di gestire manualmente i contatori del ciclo e di aggiornare le condizioni. Python fornisce un altro tipo di ciclo—il ciclo for—che eccelle in un compito diverso ma estremamente comune: elaborare ogni elemento in una collezione di dati, uno alla volta.
Il ciclo for è una delle funzionalità più usate di Python. Che tu stia elaborando righe in un file, calcolando statistiche da una sequenza di numeri o controllando ogni carattere in una stringa, il ciclo for fornisce un modo pulito e leggibile per lavorare attraverso sequenze di dati. In questo capitolo esploreremo come funzionano i cicli for, come usare la funzione range() di Python per operazioni di conteggio e come controllare l’esecuzione dei cicli con break, continue e la meno conosciuta clausola else.
12.1) Il ciclo for e i concetti di iterazione
12.1.1) Che cos’è un ciclo for?
Un ciclo for in Python ripete un blocco di codice una volta per ogni elemento in una sequenza. La sequenza potrebbe essere una stringa, una lista (list) (che studieremo in dettaglio nel Capitolo 14) o qualsiasi altra collezione di elementi. La differenza chiave rispetto a un ciclo while è che un ciclo for gestisce automaticamente l’iterazione: non hai bisogno di aggiornare manualmente un contatore o controllare una condizione.
Ecco la struttura di base di un ciclo for:
for variable in sequence:
# Blocco di codice da eseguire per ogni elemento
# La variabile contiene l'elemento correnteIl ciclo for funziona così:
- Python prende il primo elemento dalla sequenza e lo assegna alla variabile
- Il blocco di codice (rientrato sotto l’istruzione
for) viene eseguito - Python prende l’elemento successivo, lo assegna alla variabile ed esegue di nuovo il blocco
- Questo continua finché tutti gli elementi nella sequenza non sono stati elaborati
Vediamo un esempio semplice con una stringa:
# Stampa ogni carattere di un nome
name = "Alice"
for character in name:
print(character)Output:
A
l
i
c
eIn questo esempio, la stringa "Alice" è la sequenza. Il ciclo elabora ogni carattere uno alla volta. Durante la prima iterazione, character contiene 'A', durante la seconda iterazione contiene 'l' e così via. Il nome della variabile character è una nostra scelta—avremmo potuto chiamarla letter, char o persino solo c. Scegli nomi che rendano chiaro lo scopo del tuo codice.
Convenzioni di denominazione delle variabili di ciclo: Quando scrivi cicli for, scegli nomi di variabili che descrivano cosa rappresenta ciascun elemento. Usa nomi descrittivi come character, student o score quando il valore conta per comprendere il tuo codice. Usa i per semplici contatori numerici quando stai solo contando le iterazioni. Usa _ (underscore) quando non ti serve affatto il valore—questa è una convenzione Python che significa "non mi interessa questo valore."
Ecco un esempio pratico che conta le vocali in una parola:
# Conta le vocali in una parola
word = "Python"
vowel_count = 0
for letter in word:
if letter in "aeiouAEIOU":
vowel_count += 1
print(f"Trovata vocale: {letter}")
print(f"Vocali totali: {vowel_count}")Output:
Trovata vocale: o
Vocali totali: 1Il ciclo esamina ogni lettera in "Python". Quando trova una vocale (usando l’operatore in che abbiamo imparato nel Capitolo 7), incrementa il contatore e stampa un messaggio. Questo schema—inizializzare un contatore prima del ciclo, poi aggiornarlo all’interno—è estremamente comune nella programmazione.
Ecco un altro esempio che dimostra l’accumulazione costruendo un risultato:
# Conta le lettere maiuscole in una stringa
text = "Python Programming"
uppercase_count = 0
for char in text:
if char.isupper():
uppercase_count += 1
print(f"Trovate {uppercase_count} lettere maiuscole in '{text}'")Output:
Trovate 2 lettere maiuscole in 'Python Programming'Questo esempio mostra lo schema di accumulazione: inizializziamo un contatore a zero prima del ciclo, poi esaminiamo ogni carattere e incrementiamo il contatore quando troviamo una lettera maiuscola. Dopo che il ciclo termina, usiamo il risultato accumulato. Questo schema appare continuamente nella programmazione—contare elementi che soddisfano certi criteri, sommare valori o costruire risultati pezzo per pezzo.
12.1.2) Comprendere l’iterazione
Iterazione (iteration) è il processo di ripetere un’azione per ogni elemento in una collezione. Quando diciamo che un oggetto è iterabile (iterable), intendiamo che Python può elaborarne gli elementi uno alla volta in un ciclo for. Le stringhe sono iterabili—possiamo scorrere i loro caratteri. Come vedremo tra poco, molti altri tipi Python sono anch’essi iterabili.
La variabile in un ciclo for (come character o letter nei nostri esempi) è chiamata variabile di ciclo (loop variable). Questa variabile viene creata automaticamente dal ciclo for ed esiste solo nello scope del ciclo. Ogni volta che il ciclo passa, Python assegna l’elemento successivo della sequenza a questa variabile.
Ecco un esempio che mostra come cambia la variabile di ciclo:
# Mostra come la variabile di ciclo si aggiorna
colors = "RGB" # Rosso, Verde, Blu
for color_code in colors:
print(f"Elaborazione codice colore: {color_code}")
print(f" Questa è l'iterazione per '{color_code}'")Output:
Processing color code: R
This is iteration for 'R'
Processing color code: G
This is iteration for 'G'
Processing color code: B
This is iteration for 'B'Ogni volta che il ciclo passa, color_code contiene un carattere diverso della stringa. Il ciclo passa automaticamente al carattere successivo—non dobbiamo scrivere alcun codice per avanzare nella sequenza.
12.1.3) Ciclo for vs ciclo while per l’iterazione
Potremmo ottenere la stessa elaborazione carattere per carattere con un ciclo while, ma richiede più codice e gestione manuale:
# Usare un ciclo while per iterare su una stringa (più complesso)
name = "Alice"
index = 0
while index < len(name):
character = name[index]
print(character)
index += 1 # Bisogna aggiornare manualmente l'indiceQuesto produce lo stesso output del nostro precedente esempio con ciclo for, ma nota cosa abbiamo dovuto fare:
- Creare e inizializzare una variabile indice
- Controllare la condizione
index < len(name)a ogni iterazione - Estrarre manualmente il carattere usando
name[index] - Ricordarsi di incrementare l’indice (dimenticarlo crea un ciclo infinito!)
Il ciclo for gestisce tutto questo automaticamente:
# Usare un ciclo for per iterare su una stringa (più semplice)
name = "Alice"
for character in name:
print(character)Questo è molto più pulito e meno soggetto a errori. Il ciclo for è la scelta naturale quando vuoi elaborare ogni elemento in una collezione. Usa un ciclo while quando ti serve più controllo sulla logica di iterazione o quando non sai in anticipo quante volte ripetere.
12.2) Usare range() per cicli di conteggio
12.2.1) Introduzione alla funzione range()
Mentre i cicli for eccellono nell’elaborare sequenze esistenti, spesso dobbiamo ripetere un’azione un numero specifico di volte—come stampare un messaggio cinque volte o calcolare i primi dieci numeri quadrati. La funzione range() di Python genera una sequenza di numeri su cui possiamo iterare con un ciclo for.
La forma più semplice di range() accetta un argomento—il numero di interi da generare, a partire da 0:
# Stampa i numeri da 0 a 4
for number in range(5):
print(number)Output:
0
1
2
3
4⚠️ Errore comune: I principianti spesso si aspettano che range(5) produca 1, 2, 3, 4, 5, ma in realtà produce 0, 1, 2, 3, 4. Ricorda: range(n) parte da 0 e si ferma prima di n. Questo comportamento "fermati prima" è coerente con lo slicing di Python, che abbiamo visto nel Capitolo 5. Il range parte da 0 (per impostazione predefinita) e arriva fino a, ma senza includere, il valore di stop.
Questo schema è perfetto per ripetere un’azione un numero specifico di volte:
# Stampa un saluto cinque volte
for i in range(5):
print(f"Benvenuto! (iterazione {i})")Output:
Benvenuto! (iterazione 0)
Benvenuto! (iterazione 1)
Benvenuto! (iterazione 2)
Benvenuto! (iterazione 3)
Benvenuto! (iterazione 4)La variabile i è un nome comune per un contatore di ciclo (abbreviazione di "index" o "iteration"), anche se puoi usare qualsiasi nome di variabile valido. Quando il valore della variabile di ciclo non è importante per la tua logica, i è una scelta convenzionale.
12.2.2) Specificare valori di start e stop
Puoi fornire due argomenti a range() per specificare sia dove iniziare sia dove fermarti:
# Stampa i numeri da 1 a 5
for number in range(1, 6):
print(number)Output:
1
2
3
4
5Qui, range(1, 6) parte da 1 e si ferma prima di 6, dandoci i numeri da 1 a 5. Questo è utile quando devi contare a partire da un valore diverso da zero.
Usiamolo per calcolare una semplice tabellina:
# Stampa la tabellina del 7 da 1 a 10
multiplier = 7
for number in range(1, 11):
result = multiplier * number
print(f"{multiplier} × {number} = {result}")Output:
7 × 1 = 7
7 × 2 = 14
7 × 3 = 21
7 × 4 = 28
7 × 5 = 35
7 × 6 = 42
7 × 7 = 49
7 × 8 = 56
7 × 9 = 63
7 × 10 = 70Il ciclo va da 1 a 10, moltiplicando ogni numero per 7. Questo dimostra come range() renda facile eseguire calcoli su una specifica sequenza numerica.
12.2.3) Usare un valore di step
La funzione range() accetta un terzo argomento opzionale: il valore di step (step), che determina di quanto aumentare (o diminuire) tra un numero e il successivo:
# Stampa i numeri pari da 0 a 10
for number in range(0, 11, 2):
print(number)Output:
0
2
4
6
8
10Con range(0, 11, 2), partiamo da 0, ci fermiamo prima di 11 e aumentiamo di 2 ogni volta. Questo ci dà tutti i numeri pari da 0 a 10.
Puoi anche usare uno step negativo per contare all’indietro:
# Conto alla rovescia da 10 a 1
for number in range(10, 0, -1):
print(number)
print("Liftoff!")Output:
10
9
8
7
6
5
4
3
2
1
Liftoff!Qui, range(10, 0, -1) parte da 10, si ferma prima di 0 e diminuisce di 1 ogni volta. Lo step negativo fa contare il range all’indietro.
Vediamo un esempio pratico che calcola la somma di tutti i numeri dispari da 1 a 100:
# Somma tutti i numeri dispari da 1 a 100
total = 0
for number in range(1, 101, 2): # Inizia da 1, aumenta di 2
total += number
print(f"Somma dei numeri dispari da 1 a 100: {total}")Output:
Somma dei numeri dispari da 1 a 100: 2500Usando range(1, 101, 2), generiamo solo i numeri dispari (1, 3, 5, ..., 99), evitando la necessità di controllare la parità di ogni numero dentro il ciclo. Questo rende il codice più efficiente e più chiaro nell’intento.
12.2.4) Cosa restituisce davvero range()
La funzione range() non crea una lista di numeri in memoria—crea un oggetto range (range object) che genera numeri su richiesta. Questo è efficiente in termini di memoria, soprattutto per range grandi:
# range() restituisce un oggetto range, non una lista
numbers = range(1000000)
print(type(numbers)) # Output: <class 'range'>
print(numbers) # Output: range(0, 1000000)Output:
<class 'range'>
range(0, 1000000)Anche se questo range rappresenta un milione di numeri, usa pochissima memoria perché Python non crea davvero tutti i milioni di numeri finché non ci iteri sopra. Ogni numero viene generato solo quando serve al ciclo.
Se ti serve una vera lista di numeri, puoi convertire il range:
# Converti un range in una lista
small_numbers = list(range(5))
print(small_numbers) # Output: [0, 1, 2, 3, 4]Output:
[0, 1, 2, 3, 4]Impareremo di più sulle liste e sulla funzione list() nel Capitolo 14. Per ora, sappi solo che range() funziona perfettamente con i cicli for senza alcuna conversione.
12.3) Iterare su stringhe e altre sequenze
12.3.1) Iterare sulle stringhe carattere per carattere
Abbiamo già visto diversi esempi di iterazione sulle stringhe. Questo è uno degli usi più comuni dei cicli for perché le stringhe sono sequenze di caratteri e spesso dobbiamo esaminare o elaborare ogni carattere individualmente.
Ecco un esempio che valida una password controllando che contenga almeno una cifra:
# Verifica se una password contiene almeno una cifra
password = "secure123"
has_digit = False
for character in password:
if character.isdigit():
has_digit = True
print(f"Trovata cifra: {character}")
if has_digit:
print("La password contiene almeno una cifra ✓")
else:
print("La password deve contenere almeno una cifra ✗")Output:
Trovata cifra: 1
Trovata cifra: 2
Trovata cifra: 3
La password contiene almeno una cifra ✓Il ciclo esamina ogni carattere usando il metodo di stringa .isdigit() (che abbiamo imparato nel Capitolo 5). Quando trova una cifra, imposta has_digit a True. Dopo che il ciclo termina, controlliamo il flag per determinare se è stata trovata almeno una cifra.
Ecco un altro esempio pratico che conta diversi tipi di caratteri:
# Analizza i tipi di caratteri in una stringa
text = "Hello, World! 123"
letters = 0
digits = 0
spaces = 0
other = 0
for char in text:
if char.isalpha():
letters += 1
elif char.isdigit():
digits += 1
elif char.isspace():
spaces += 1
else:
other += 1
print(f"Letters: {letters}")
print(f"Digits: {digits}")
print(f"Spaces: {spaces}")
print(f"Other: {other}")Output:
Letters: 10
Digits: 3
Spaces: 2
Other: 2Questo ciclo categorizza ogni carattere usando metodi di stringa che abbiamo imparato nel Capitolo 5. La catena if-elif-else (dal Capitolo 8) garantisce che ogni carattere venga contato in esattamente una categoria.
12.3.2) Elaborare stringhe con indici
A volte ti servono sia il carattere sia la sua posizione nella stringa. Puoi usare range(len(string)) per iterare sugli indici:
# Trova le posizioni di un carattere specifico
text = "Mississippi"
search_char = "s"
print(f"Cerco '{search_char}' in '{text}':")
for index in range(len(text)):
if text[index] == search_char:
print(f" Trovato all'indice {index}")Output:
Cerco 's' in 'Mississippi':
Trovato all'indice 2
Trovato all'indice 3
Trovato all'indice 5
Trovato all'indice 6Il ciclo itera sugli indici da 0 a len(text) - 1. Per ogni indice, controlliamo se il carattere in quella posizione corrisponde al carattere cercato. Questo approccio è utile quando devi sapere dove appare qualcosa, non solo che appare.
12.3.3) Iterare su altri tipi di sequenza
Il ciclo for funziona con qualsiasi sequenza iterabile in Python. Anche se in questo capitolo ci siamo concentrati sulle stringhe, imparerai altri tipi di sequenza nei capitoli successivi. Per esempio, il Capitolo 14 ti insegnerà le liste, che sono collezioni ordinate che possono contenere più valori di qualsiasi tipo. La sintassi del ciclo for rimane la stessa indipendentemente dal tipo di sequenza su cui stai iterando—il ciclo gestisce automaticamente l’ottenimento di ciascun elemento dalla sequenza.
12.4) Usare break e continue nei cicli for
12.4.1) L’istruzione break nei cicli for
Proprio come con i cicli while (Capitolo 11), l’istruzione break esce immediatamente da un ciclo for, saltando tutte le iterazioni rimanenti. Questo è utile quando hai trovato ciò che stai cercando e non devi continuare a cercare.
Ecco un esempio che cerca un carattere specifico:
# Cerca la prima vocale in una stringa
text = "Python"
found_vowel = False
for char in text:
if char.lower() in "aeiou":
print(f"Prima vocale trovata: {char}")
found_vowel = True
break # Smetti di cercare una volta trovata la prima vocale
if not found_vowel:
print("Nessuna vocale trovata")Output:
Prima vocale trovata: oSenza break, il ciclo continuerebbe a esaminare tutti i caratteri rimanenti anche dopo aver trovato la prima vocale. L’istruzione break rende il codice più efficiente fermandosi non appena il compito è completato.
Ecco un esempio pratico che valida l’input dell’utente controllando la presenza di caratteri non validi:
# Verifica se un nome utente contiene solo caratteri consentiti
username = "alice_123"
allowed = "abcdefghijklmnopqrstuvwxyz0123456789_"
is_valid = True
for char in username:
if char.lower() not in allowed:
print(f"Carattere non valido trovato: '{char}'")
is_valid = False
break # Non serve controllare oltre
if is_valid:
print(f"Username '{username}' è valido ✓")
else:
print(f"Username '{username}' non è valido ✗")Output:
Username 'alice_123' è valido ✓Il ciclo controlla ogni carattere rispetto all’insieme consentito. Se trova un carattere non valido, segnala il problema e interrompe subito il ciclo—non ha senso controllare il resto del nome utente una volta che sappiamo che non è valido.
12.4.2) L’istruzione continue nei cicli for
L’istruzione continue salta il resto dell’iterazione corrente e passa all’elemento successivo della sequenza. Questo è utile quando vuoi saltare alcuni elementi senza uscire del tutto dal ciclo.
Ecco un esempio che elabora solo certi caratteri:
# Stampa solo le consonanti di una stringa
word = "Programming"
for letter in word:
if letter.lower() in "aeiou":
continue # Salta le vocali
print(letter, end="")
print() # Nuova riga alla fineOutput:
PrgrmmngQuando il ciclo incontra una vocale, continue salta l’istruzione print() e passa al carattere successivo. Solo le consonanti arrivano alla stampa.
Ecco un esempio più pratico che calcola statistiche saltando dati non validi. Nota che il metodo .split() (dal Capitolo 6) restituisce una lista di stringhe, che studieremo nel Capitolo 14. Per ora, sappi solo che i cicli for possono iterare sul risultato:
# Calcola la media dei punteggi validi (0-100)
# Il metodo .split() restituisce una lista di stringhe (Capitolo 14)
scores_input = "85 92 -5 78 105 90 88"
valid_scores = 0
total = 0
for score_str in scores_input.split():
score = int(score_str)
if score < 0 or score > 100:
print(f"Salto punteggio non valido: {score}")
continue # Salta questo punteggio
valid_scores += 1
total += score
if valid_scores > 0:
average = total / valid_scores
print(f"Media di {valid_scores} punteggi validi: {average:.1f}")
else:
print("Nessun punteggio valido per calcolare la media")Output:
Skipping invalid score: -5
Skipping invalid score: 105
Average of 5 valid scores: 86.6Il ciclo elabora ogni stringa di punteggio. Quando incontra un punteggio non valido (negativo o sopra 100), stampa un avviso e usa continue per saltare l’aggiunta di quel punteggio al totale. Questo permette al ciclo di elaborare tutti i punteggi validi ignorando quelli non validi.
12.4.3) Quando usare break e continue
Usa break quando:
- Stai cercando qualcosa e vuoi fermarti una volta che l’hai trovato
- Hai incontrato una condizione di errore che rende inutile continuare
- Hai completato il tuo compito e non devi elaborare gli elementi rimanenti
Usa continue quando:
- Vuoi saltare certi elementi in base a una condizione
- Stai filtrando dati e vuoi elaborare solo gli elementi che soddisfano criteri
- Vuoi evitare istruzioni
ifprofondamente annidate gestendo i casi speciali in anticipo
Sia break sia continue possono rendere il codice più chiaro mostrando esplicitamente quando e perché stai cambiando il normale flusso di iterazione. Tuttavia, abusarne può rendere il codice più difficile da seguire—usali quando migliorano davvero la chiarezza.
12.5) Usare else con i cicli for
12.5.1) Il pattern for-else
I cicli for di Python supportano una clausola opzionale else che viene eseguita dopo che il ciclo termina normalmente—cioè quando il ciclo ha finito di iterare su tutti gli elementi senza incontrare un’istruzione break. Questo può sembrare strano all’inizio (perché "else" se non c’è "if"?), ma è utile per distinguere tra "ho trovato ciò che cercavo" e "ho cercato ovunque e non l’ho trovato."
Ecco la struttura di base:
for item in sequence:
# Corpo del ciclo
if some_condition:
break
else:
# Questo viene eseguito solo se il ciclo è terminato senza break
print("Il ciclo è terminato normalmente")Il blocco else viene eseguito se e solo se il ciclo esce in modo naturale esaurendo la sequenza. Se un’istruzione break esce dal ciclo in anticipo, il blocco else viene saltato.
Vediamo un esempio pratico che cerca un valore specifico. Il metodo .split() (dal Capitolo 6) restituisce una lista di stringhe, che studieremo nel Capitolo 14:
# Cerca un numero obiettivo
numbers = "2 4 6 8 10"
target = 7
for num_str in numbers.split():
num = int(num_str)
if num == target:
print(f"Trovato {target}!")
break
else:
print(f"{target} non trovato nella sequenza")Output:
7 non trovato nella sequenzaIl ciclo cerca in tutti i numeri. Poiché non trova mai 7, termina normalmente e viene eseguito il blocco else. Ora cerchiamo un numero che esiste:
# Cerca un numero obiettivo che esiste
numbers = "2 4 6 8 10"
target = 6
for num_str in numbers.split():
num = int(num_str)
if num == target:
print(f"Trovato {target}!")
break
else:
print(f"{target} non trovato nella sequenza")Output:
Trovato 6!Questa volta, quando il ciclo trova 6, esegue break, che salta completamente il blocco else. Questo pattern gestisce elegantemente sia il caso "trovato" sia il caso "non trovato" senza bisogno di una variabile flag separata.
12.5.2) Usi pratici di for-else
Il pattern for-else è particolarmente utile per operazioni di ricerca. Ecco un esempio che valida se una stringa contiene solo cifre:
# Verifica se una stringa è un intero valido
user_input = "12345"
for char in user_input:
if not char.isdigit():
print(f"Non valido: '{char}' non è una cifra")
break
else:
print(f"'{user_input}' è un intero valido")Output:
'12345' è un intero validoSe l’input contiene qualsiasi carattere non numerico, il ciclo si interrompe e il blocco else non viene eseguito. Se tutti i caratteri sono cifre, il ciclo termina normalmente e il blocco else conferma la validità.
Testiamolo con input non valido:
# Verifica se una stringa è un intero valido (caso non valido)
user_input = "123a5"
for char in user_input:
if not char.isdigit():
print(f"Non valido: '{char}' non è una cifra")
break
else:
print(f"'{user_input}' è un intero valido")Output:
Non valido: 'a' non è una cifra12.5.3) Confrontare for-else con variabili flag
Prima di imparare for-else, potresti aver usato una variabile flag per tracciare se qualcosa è stato trovato:
# Usare una variabile flag (approccio tradizionale)
text = "Python"
found_vowel = False
for char in text:
if char.lower() in "aeiou":
print(f"Trovata vocale: {char}")
found_vowel = True
break
if not found_vowel:
print("Nessuna vocale trovata")Output:
Found vowel: oIl pattern for-else elimina la necessità della variabile flag:
# Usare for-else (più Pythonico)
text = "Python"
for char in text:
if char.lower() in "aeiou":
print(f"Trovata vocale: {char}")
break
else:
print("Nessuna vocale trovata")Output:
Found vowel: oEntrambi gli approcci funzionano correttamente, ma la versione for-else è più concisa ed esprime chiaramente l’intento: "cerca qualcosa, e se non la trovi, fai questo." La clausola else rappresenta direttamente il caso "non trovato".
12.6) Scegliere tra cicli for e while
12.6.1) Quando usare un ciclo for
Usa un ciclo for quando:
1. Stai elaborando ogni elemento in una collezione:
# Elaborare ogni carattere in una stringa
message = "Hello"
for char in message:
print(char.upper())Output:
H
E
L
L
O2. Devi ripetere un’azione un numero specifico di volte:
# Stampa una linea di bordo
for i in range(40):
print("-", end="")
print()Output:
----------------------------------------3. Stai iterando su un intervallo numerico:
# Calcola il fattoriale di 5
factorial = 1
for n in range(1, 6):
factorial *= n
print(f"5! = {factorial}")Output:
5! = 1204. Sai in anticipo su cosa stai iterando:
# Elabora una sequenza nota di valori
grades = "A B C D F"
for grade in grades.split():
print(f"Voto: {grade}")Output:
Voto: A
Voto: B
Voto: C
Voto: D
Voto: FLa caratteristica chiave dei cicli for è che lavorano con la cosiddetta “iterazione definita” (definite iteration)—sai su quale sequenza stai iterando, anche se non sai in anticipo quanti elementi contiene.
12.6.2) Quando usare un ciclo while
Usa un ciclo while quando:
1. Stai ripetendo finché una condizione cambia:
# Continua a chiedere finché non viene ricevuto un input valido
while True:
age_input = input("Enter your age: ")
if age_input.isdigit():
age = int(age_input)
if age > 0:
print(f"Age recorded: {age}")
break
print("Please enter a valid positive number")2. Non sai di quante iterazioni avrai bisogno:
# Conta quante volte puoi raddoppiare un numero prima di superare 1000
number = 1
count = 0
while number <= 1000:
number *= 2
count += 1
print(f"Raddoppiato {count} volte per arrivare a {number}")Output:
Raddoppiato 10 volte per arrivare a 10243. L’iterazione dipende da condizioni complesse:
# Simula un semplice gioco in cui la salute del giocatore diminuisce
health = 100
turn = 0
while health > 0 and turn < 10:
damage = 15
health -= damage
turn += 1
print(f"Turn {turn}: Health = {health}")
if health <= 0:
print("Game over!")
else:
print("Survived 10 turns!")Output:
Turn 1: Health = 85
Turn 2: Health = 70
Turn 3: Health = 55
Turn 4: Health = 40
Turn 5: Health = 25
Turn 6: Health = 10
Turn 7: Health = -5
Game over!4. Hai bisogno di più controllo sulla logica di iterazione:
# Elabora una stringa ma salta i duplicati consecutivi
text = "bookkeeper"
index = 0
while index < len(text):
char = text[index]
print(char, end="")
# Salta i caratteri consecutivi identici
while index < len(text) and text[index] == char:
index += 1
print()Output:
bokeperLa caratteristica chiave dei cicli while è che si parla di “iterazione indefinita” (indefinite iteration)—continui finché una condizione diventa falsa, ma potresti non sapere in anticipo quando accadrà.
12.6.3) Convertire tra for e while
Molti problemi possono essere risolti con entrambi i tipi di ciclo. Ecco lo stesso compito implementato in entrambi i modi:
# Usare un ciclo for: somma i numeri da 1 a 10
total = 0
for number in range(1, 11):
total += number
print(f"Somma (ciclo for): {total}")
# Usare un ciclo while: somma i numeri da 1 a 10
total = 0
number = 1
while number <= 10:
total += number
number += 1
print(f"Somma (ciclo while): {total}")Output:
Sum (for loop): 55
Sum (while loop): 55Entrambi producono lo stesso risultato, ma il ciclo for è più conciso e meno soggetto a errori—non c’è rischio di dimenticare di incrementare il contatore. Quando puoi usare entrambi, preferisci il ciclo for.
Tuttavia, alcuni problemi sono espressi più naturalmente con while:
# Trova la prima potenza di 2 maggiore di 1000
power = 1
exponent = 0
while power <= 1000:
exponent += 1
power = 2 ** exponent
print(f"2^{exponent} = {power} (first power of 2 > 1000)")Output:
2^10 = 1024 (first power of 2 > 1000)Questo problema non si adatta naturalmente a un ciclo for perché non sappiamo in anticipo quante iterazioni ci servono—stiamo cercando un valore che soddisfi una condizione.
In questo capitolo abbiamo esplorato il ciclo for di Python, che fornisce un modo pulito e potente per iterare su sequenze. Abbiamo imparato come range() generi sequenze numeriche per operazioni di conteggio, come controllare il flusso del ciclo con break e continue e come il pattern for-else gestisca elegantemente le operazioni di ricerca. Abbiamo anche esaminato quando scegliere i cicli for rispetto ai cicli while in base alla natura del compito di iterazione.
Il ciclo for è una delle funzionalità più usate di Python. Man mano che continui a imparare Python, userai i cicli for continuamente—elaborando dati da file, lavorando con liste e dizionari e trasformando collezioni di informazioni. Nel prossimo capitolo esploreremo l’istruzione match di Python, che fornisce un altro modo per prendere decisioni in base ai valori, offrendo un’alternativa più strutturata a lunghe catene if-elif per certi tipi di problemi.