Tomar decisiones: if, elif, else
Tomar caminos distintos según una condición, por qué la sangría tiene significado en Python y el error silencioso que se produce al ordenar mal las condiciones.
¿Cómo quieres aprender?
El problema que vamos a resolver
En el capítulo anterior aprendimos a hacer preguntas: ¿age >= 18 es verdadero o falso? Pero, aunque el programa conocía la respuesta, no hacía nada con ella; solo la imprimía como True o False.
Ahora toca actuar según esa respuesta: un camino si la condición se cumple y otro si no. Aquí es donde el código deja de ser una lista de pasos y empieza a tomar decisiones.
Y en este punto Python se diferencia de muchos otros lenguajes de programación: qué líneas están dentro de una condición y cuáles están fuera lo decide la sangría (los espacios al principio de cada línea). No hay llaves {}. Al principio resulta extraño, pero luego empieza a gustarte, porque un código que parece ordenado, lo está.
Al terminar este capítulo podrás
- Ejecutar código de forma condicional con
if - Dar una alternativa con
else, y varias conelif - Aplicar la sangría correctamente, y leer y corregir un
IndentationError - Explicar por qué importa el orden de las condiciones: la trampa más grande de este tema
- Anidar una condición dentro de otra, y reconocer cuándo conviene evitarlo
Requisitos previos: True y False: aprender a hacer preguntas.
La forma más sencilla
age = 22
if age >= 18:
print("You may enter")
print("Program finished")You may enter
Program finishedLa estructura tiene tres partes:
- La palabra
if, seguida de una condición - Unos dos puntos
:al final de la condición; olvidarlos es el error más habitual - Las líneas siguientes, con una sangría de cuatro espacios: esas líneas con sangría son las que dependen de la condición
Si age valiera 15, el primer print no se ejecutaría, pero el último sí, porque está fuera de la condición.
La sangría cambia el significado
Estos dos programas tienen casi los mismos caracteres y se comportan de forma completamente distinta:
score = 30
if score >= 50:
print("Passed")
print("Certificate issued")Ejecútalo y no aparece nada en la terminal: las dos líneas están dentro de la condición, y la condición es falsa.
score = 30
if score >= 50:
print("Passed")
print("Certificate issued")Certificate issuedEl segundo print ahora está fuera de la condición, así que siempre se ejecuta, y se acaba de emitir un certificado a alguien que no aprobó. Una sola línea con mala sangría rompe la regla de negocio, y Python no lanza ningún error, porque ambas versiones son código válido.
Cuatro espacios, no tabulaciones. Python acepta cualquiera de los dos, pero mezclarlos en un mismo archivo produce un TabError, y es doloroso de encontrar porque en pantalla los tabuladores y los espacios se ven iguales. En VS Code, que instalaste en el capítulo 1, pulsar Tab en un archivo de Python inserta cuatro espacios: es su configuración por defecto, y cuatro espacios es la convención oficial de Python.else — el otro camino
age = 15
if age >= 18:
print("You may enter")
else:
print("Sorry, adults only")Sorry, adults onlyelse no lleva condición, porque su condición ya está dicha: «si nada de lo anterior se cumplió». Exactamente uno de los dos, el if o el else, se ejecuta; nunca los dos, nunca ninguno.
elif — varios caminos
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 «si no, si». Lo que ocurre es esto: Python recorre la serie de condiciones de arriba abajo, ejecuta el bloque de la primera condición que encuentra verdadera y luego sale de toda la serie. Ni siquiera comprueba las demás.
Con marks = 72: 72 >= 80 es falso, 72 >= 70 es verdadero → grade = "B", listo. 72 >= 60 y 72 >= 40 también son verdaderos, pero nunca llegan a mirarse.
Y aquí está la trampa más grande
Como elif se detiene en la primera condición verdadera, equivocarse en el orden produce un programa que se ejecuta, no lanza ningún error y responde mal:
marks = 95
if marks >= 40:
grade = "Pass"
elif marks >= 80:
grade = "Excellent"
else:
grade = "Fail"
print(grade)Pass95 puntos y sin Excellent. Porque 95 >= 40 era verdadero de inmediato, y Python se detuvo ahí: la segunda condición ni siquiera llegó a comprobarse.
La regla que hay que recordar: pon primero la condición más estricta y específica, y la más flexible al final. Cuando trabajes con tramos numéricos, recórrelos empezando por el más alto, como en el ejemplo de las notas de arriba.
Este error es tan silencioso que solo se detecta viéndolo. Así que conviértelo en un hábito: después de escribir una serie de condiciones, ejecútala una vez con un valor para cada rama. El código de las notas de arriba debería dar cinco respuestas distintas para 95, 72, 65, 45 y 20. Si dos coinciden, el orden está mal.
Una condición dentro de otra condición
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, userEl if interior tiene cuatro espacios de sangría, porque cuelga del exterior, y sus propias líneas de print van con ocho. Funciona, pero cuantos más niveles hay, más difícil es leer el código. A menudo and dice lo mismo con más claridad:
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, userCuál es mejor depende de cuál se lea con más facilidad. Cuando te encuentres a más de tres niveles de profundidad, para y replantéalo: casi siempre es señal de que las condiciones se pueden organizar de otra manera.
Validar la entrada
Ahora tenemos la herramienta que resuelve el problema que quedó pendiente en un capítulo anterior: qué hacer cuando alguien no escribe nada o escribe una palabra:
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() es un método nuevo: indica si todos los caracteres del texto son dígitos. Es la forma sencilla de comprobar algo antes de pasárselo a int(), y hace que desaparezca el ValueError. (isdigit() no acepta negativos ni decimales; para eso hace falta try, que veremos más adelante.)
Un ejemplo 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.80Fíjate en dos decisiones de diseño. Primero, las condiciones de edad van encadenadas con elif, porque cada pasajero cae en exactamente una categoría. Segundo, la condición del fin de semana es un if aparte, porque es una pregunta independiente: sea cual sea la edad, el recargo de fin de semana se aplica encima. Decidir qué es un elif y qué es un if separado es el trabajo real de escribir condiciones.
Cuando algo falla
SyntaxError: expected ':' Falta el : al final de la línea del if, elif o else.
IndentationError: expected an indented block after 'if' statement La línea que sigue al if no tiene sangría. Una condición necesita al menos una línea dentro.
IndentationError: unexpected indent Alguna línea tiene sangría sin motivo. Averigua a qué bloque debería pertenecer esa línea.
TabError: inconsistent use of tabs and spaces in indentation Hay tabulaciones y espacios mezclados en el mismo archivo. Ejecuta «convertir la sangría a espacios» en tu editor.
SyntaxError — un elif o un else suelto elif y else siempre pertenecen a un if, y deben tener la misma sangría que ese if.
TypeError: '>=' not supported between instances of 'str' and 'int' Se te olvidó convertir el input(). Escribe int(input(...)).
Las condiciones parecen correctas, pero toman el camino equivocado Revisa el orden. Si una condición flexible va primero, la estricta nunca se comprueba. Ejecútalo una vez con un valor para cada rama.
Paso 4 de 6 — Predice
Comprueba lo que has entendido
Con 85 puntos, ¿qué imprime este programa?
marks = 85
if marks >= 40:
print("Pass")
elif marks >= 80:
print("Excellent")
else:
print("Fail")- AExcellent Pass
- BPass
- CPass Excellent
- DExcellent
¿Qué imprime este programa?
score = 30
if score >= 50:
print("Passed")
print("Done")- APassed Done
- BDone
- CNo se imprime nada
- DPassed
Incluso cuando la persona escribe 25, esto se detiene con un TypeError. ¿Cuál es la causa y cuál es la solución?
age = input("Age: ")
if age >= 18:
print("Adult")
else:
print("Minor")- A`input()` devuelve texto, y el texto no se puede comparar con un número: hace falta `age = int(input("Age: "))`
- BHace falta un `elif` antes de un `else`
- C`>=` no se puede usar en una condición `if`; tiene que ser `>`
- D`age` es una palabra reservada, por eso falló la comparación
Para responder necesitas una cuenta
Inicia sesión para comprobar tus respuestas
Las preguntas están arriba, y resolverlas mentalmente es lo que de verdad importa. Inicia sesión para ver las respuestas, las explicaciones y las pistas de tres niveles.
Tu turno
Escribe un archivo llamado bmi.py que reciba una altura en metros y un peso en kilogramos, calcule el IMC y muestre la categoría.
La fórmula: bmi = weight / (height * height)
Las categorías:
- Menos de 18.5 — Bajo peso
- 18.5 o más, pero menos de 25 — Normal
- 25 o más, pero menos de 30 — Sobrepeso
- 30 o más — Obesidad
Los límites están escritos con «menos de» (<) y «o más» (>=) a propósito. Escribir «de 18.5 a 24.9» deja un hueco en medio: un IMC como 24.95 no caería en ninguna categoría. Con < y >=, cada número cae en exactamente una categoría.
Cuatro condiciones:
- Muestra el IMC con un decimal
- Ordena las condiciones para que las cuatro categorías funcionen de verdad
- Si la altura es
0, detente antes de dividir e imprime un mensaje; si no, obtendrás unZeroDivisionError - Ejecútalo con cuatro valores que cubran las cuatro categorías, y también con valores justo en los límites: ¿en qué categoría cae un IMC de exactamente 25? (Debería ser Sobrepeso.)
Esa cuarta condición es la importante. Los valores justo sobre un límite son donde aparecen los errores de orden en las condiciones.
Esta misión tiene más
Lo que has leído arriba es la misión completa: no se ha recortado nada. Pro añade:
- Qué ocurre realmente por debajo: cómo ejecuta Python esto
- La solución completa del ejercicio, resuelta paso a paso
- Ejercicios extra más difíciles
- La pregunta de entrevista sobre este tema, con una respuesta modelo
Paso 6 de 6
Reto — el quiz del capítulo
Diez preguntas de fácil a difícil. Las últimas son difíciles a propósito.
Inicia sesión para hacer el quiz