Prendere decisioni — if, elif, else
Scegliere percorsi diversi in base a una condizione, perché l'indentazione ha significato in Python, e il bug silenzioso causato dall'ordine sbagliato delle condizioni.
Come vuoi imparare?
Il problema che stiamo risolvendo
Nel capitolo precedente abbiamo imparato a porre domande — age >= 18 è vera o falsa? Ma una volta conosciuta la risposta, il programma non faceva nulla con essa: si limitava a stampare True o False.
Ora è il momento di agire in base a quella risposta. Un percorso se la condizione è vera, un altro se non lo è. È il momento in cui il codice smette di essere una lista di passaggi e comincia a prendere decisioni.
E qui Python si differenzia da molti altri linguaggi di programmazione: quali righe stanno dentro una condizione e quali stanno fuori è deciso dagli spazi bianchi. Non ci sono parentesi graffe {}. All'inizio sembra strano, poi inizi ad apprezzarlo — perché il codice che sembra ordinato, lo è davvero.
Alla fine di questo capitolo sarai in grado di
- Eseguire codice in modo condizionale con
if - Prevedere un'alternativa con
else, e più alternative conelif - Indentare correttamente, e leggere e correggere un
IndentationError - Spiegare perché l'ordine delle condizioni conta — la trappola più grande di questo argomento
- Annidare una condizione dentro un'altra, e riconoscere quando è meglio evitarlo
Prerequisiti: True e False — imparare a porre domande.
La forma più semplice
age = 22
if age >= 18:
print("You may enter")
print("Program finished")You may enter
Program finishedLa struttura ha tre parti:
- La parola
if, seguita da una condizione - Due punti
:alla fine della condizione — dimenticarli è l'errore più comune - Le righe che seguono, indentate di quattro spazi — sono quelle righe che la condizione controlla
Se age fosse stato 15, il primo print non sarebbe stato eseguito, ma l'ultimo sì — perché sta fuori dalla condizione.
L'indentazione è il significato
Questi due programmi hanno quasi gli stessi caratteri e si comportano in modo completamente diverso:
score = 30
if score >= 50:
print("Passed")
print("Certificate issued")Eseguilo e non compare nulla nel terminale — entrambe le righe sono dentro la condizione, e la condizione è falsa.
score = 30
if score >= 50:
print("Passed")
print("Certificate issued")Certificate issuedLa seconda print ora sta fuori dalla condizione, quindi viene sempre eseguita — e un certificato è appena stato rilasciato a qualcuno che non ha superato l'esame. Una sola riga indentata male rompe la regola del programma, e Python non segnala alcun errore, perché entrambe le versioni sono codice valido.
Quattro spazi, non tabulazioni. Python accetta entrambi, ma mescolarli nello stesso file produce un TabError, ed è difficile da trovare perché tabulazioni e spazi sembrano identici sullo schermo. In VS Code, che hai installato nel capitolo 1, premere Tab in un file Python inserisce quattro spazi — è l'impostazione predefinita, e quattro spazi è la convenzione ufficiale di Python.else — l'altro percorso
age = 15
if age >= 18:
print("You may enter")
else:
print("Sorry, adults only")Sorry, adults onlyelse non ha una condizione, perché la sua condizione è già stata dichiarata — "se nessuna delle precedenti era vera". Esattamente uno tra if ed else viene eseguito: mai entrambi, mai nessuno dei due.
elif — più percorsi
marks = 72
if marks >= 80:
grade = "A"
elif marks >= 70:
grade = "B"
elif marks >= 60:
grade = "C"
elif marks >= 40:
grade = "D"
else:
grade = "F"
print(f"Marks {marks} gives grade {grade}")Marks 72 gives grade Belif significa "altrimenti, se". Ecco cosa succede: Python scende lungo la catena, esegue il corpo della prima condizione che trova vera, e poi abbandona l'intera catena. Non verifica nemmeno le altre.
Con marks = 72: 72 >= 80 è falsa, 72 >= 70 è vera → grade = "B", fine. 72 >= 60 e 72 >= 40 sono vere anche loro, ma non vengono mai esaminate.
E qui c'è la trappola più grande
Poiché elif si ferma alla prima condizione vera, sbagliare l'ordine produce un programma che gira, non segnala errori e risponde in modo scorretto:
marks = 95
if marks >= 40:
grade = "Pass"
elif marks >= 80:
grade = "Excellent"
else:
grade = "Fail"
print(grade)PassCon 95 voti il programma stampa Pass, non Excellent. Perché 95 >= 40 era vera subito, e Python si è fermato lì — la seconda condizione non è mai stata verificata.
La regola da ricordare: metti per primo la condizione più stretta e specifica, e per ultima quella più larga. Quando lavori con fasce numeriche, scendi dal valore più alto, come nell'esempio dei voti qui sopra.
Questo bug è così silenzioso che l'unico modo per beccarlo è provare il codice. Quindi fanne un'abitudine: dopo aver scritto una catena di condizioni, eseguila una volta con un valore per ciascun ramo. Il codice dei voti qui sopra dovrebbe dare cinque risposte diverse per 95, 72, 65, 45 e 20. Se due risposte coincidono, l'ordine è sbagliato.
Una condizione dentro un'altra
is_logged_in = True
is_admin = False
if is_logged_in:
if is_admin:
print("Welcome, admin")
else:
print("Welcome, user")
else:
print("Please log in")Welcome, userL'if interno è indentato di quattro spazi, perché sta sotto quello esterno, e le sue righe print sono indentate di otto. Funziona, ma più livelli ci sono, più il codice è difficile da leggere. Spesso and dice la stessa cosa in modo più chiaro:
is_logged_in = True
is_admin = False
if is_logged_in and is_admin:
print("Welcome, admin")
elif is_logged_in:
print("Welcome, user")
else:
print("Please log in")Welcome, userQuale delle due sia migliore dipende da quale si legge più facilmente. Quando ti ritrovi a più di tre livelli di profondità, fermati e ripensaci — quasi sempre è un segno che le condizioni si possono organizzare diversamente.
Validare l'input
Ora abbiamo lo strumento che risolve il problema lasciato aperto in un capitolo precedente — cosa fare quando qualcuno non scrive nulla, o scrive una parola:
raw = input("Your age: ").strip()
if raw == "":
print("You did not type anything")
elif raw.isdigit():
age = int(raw)
if age >= 18:
print(f"Age {age}: you may enter")
else:
print(f"Age {age}: adults only")
else:
print(f"'{raw}' is not a whole number")Your age: twenty
'twenty' is not a whole numberisdigit() è un nuovo metodo — verifica se ogni carattere del testo è una cifra. È il modo semplice per controllare prima di passare qualcosa a int(), e fa sparire ValueError. (isdigit() non accetta numeri negativi né decimali — quelli richiedono try, che arriverà più avanti.)
Un esempio completo
fare.py:
# Work out a ticket fare from age and day of week
age = int(input("Passenger age : "))
day = input("Day of week : ").strip().lower()
base_fare = 120.0
# Most specific rule first, loosest last
if age < 5:
fare = 0.0
category = "Infant"
elif age < 18:
fare = base_fare * 0.5
category = "Child"
elif age >= 60:
fare = base_fare * 0.7
category = "Senior"
else:
fare = base_fare
category = "Adult"
is_weekend = day == "saturday" or day == "sunday"
if is_weekend:
fare = fare * 1.2
print()
print(f"Category : {category}")
print(f"Weekend : {is_weekend}")
print(f"Fare : {fare:.2f}")Passenger age : 65
Day of week : Sunday
Category : Senior
Weekend : True
Fare : 100.80Nota due scelte di progettazione. Primo, le condizioni sull'età sono concatenate con elif, perché un passeggero rientra in esattamente una categoria. Secondo, la condizione del weekend è un if separato, perché è una domanda indipendente — qualunque sia l'età, la maggiorazione del weekend si applica in aggiunta. Decidere cosa è un elif e cosa è un if separato è il vero lavoro nello scrivere condizioni.
Quando qualcosa va storto
SyntaxError: expected ':' Mancano i due punti alla fine della riga if, elif o else.
IndentationError: expected an indented block after 'if' statement La riga dopo l'if non è indentata. Una condizione deve avere almeno una riga al suo interno.
IndentationError: unexpected indent Una riga è indentata senza motivo. Individua a quale blocco dovrebbe appartenere quella riga.
TabError: inconsistent use of tabs and spaces in indentation Tabulazioni e spazi sono mescolati nello stesso file. Usa il comando del tuo editor per convertire l'indentazione in spazi.
SyntaxError — un elif o un else da solo elif ed else appartengono sempre a un if, e devono essere indentati allo stesso livello di quell'if.
TypeError: '>=' not supported between instances of 'str' and 'int' Hai dimenticato di convertire il valore di input(). Scrivi int(input(...)).
Le condizioni sembrano giuste ma prendono il percorso sbagliato Controlla l'ordine. Con una condizione larga per prima, quella più stretta non viene mai verificata. Eseguilo una volta con un valore per ciascun ramo.
Passo 4 di 6 — Prevedi
Verifica cosa hai capito
Con 85 voti, che cosa stampa questo programma?
marks = 85
if marks >= 40:
print("Pass")
elif marks >= 80:
print("Excellent")
else:
print("Fail")- AExcellent Pass
- BPass
- CPass Excellent
- DExcellent
Che cosa stampa questo programma?
score = 30
if score >= 50:
print("Passed")
print("Done")- APassed Done
- BDone
- CNiente
- DPassed
Anche quando la persona digita 25, questo si blocca con un TypeError. Qual è la causa e qual è la correzione?
age = input("Age: ")
if age >= 18:
print("Adult")
else:
print("Minor")- A`input()` restituisce testo, e il testo non può essere confrontato con un numero — serve `age = int(input("Age: "))`
- BUn `elif` è obbligatorio prima di un `else`
- C`>=` non può essere usato in una condizione `if`; deve essere `>`
- D`age` è una parola riservata, quindi il confronto non è riuscito
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 bmi.py che riceve un'altezza in metri e un peso in chilogrammi, calcola il BMI e indica la categoria.
La formula: bmi = weight / (height * height)
Le categorie:
- Sotto 18,5 — Underweight
- Da 18,5 incluso, ma sotto 25 — Normal
- Da 25 incluso, ma sotto 30 — Overweight
- Da 30 in su — Obese
I limiti sono scritti con "sotto" (<) e "da ... in su" (>=) di proposito. Scrivere "da 18,5 a 24,9" lascia un vuoto nel mezzo — un BMI come 24,95 non cadrebbe in nessuna categoria. Con < e >=, ogni numero cade in esattamente una categoria.
Quattro requisiti:
- Mostra il BMI con una cifra decimale
- Ordina le condizioni in modo che tutte e quattro le categorie funzionino davvero
- Se l'altezza è
0, fermati prima di dividere e stampa un messaggio — altrimenti ottieni unZeroDivisionError - Eseguilo con quattro valori che coprano le quattro categorie, e anche con valori esattamente sui limiti — in quale categoria cade un BMI di esattamente 25? (Dovrebbe essere Overweight.)
Il quarto punto è quello importante. I valori che cadono proprio sul limite sono il punto in cui emergono gli errori nell'ordine delle condizioni.
In questa missione c’è di più
Quello che hai letto sopra è la missione completa: non è stato tagliato nulla. Pro aggiunge:
- Cosa succede davvero dietro le quinte: come Python lo esegue
- La soluzione completa dell’esercizio, svolta passo per passo
- Esercizi extra più difficili
- La domanda da colloquio su questo argomento, con una risposta modello
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