Al final del módulo anterior dejamos el proyecto Papyrus con su entorno listo y varios scripts funcionando, y prometimos que tus programas empezarían a tomar decisiones. Esta lección cumple esa promesa: aprenderás a usar if, elif y else para que Python ejecute un código u otro según las condiciones que se cumplan. Es la diferencia entre un script que siempre hace lo mismo y un programa que reacciona: "¿hay stock de La Odisea?", "¿Luis es socio? Entonces aplícale el descuento". Sin condicionales no hay lógica de negocio posible, así que esta es probablemente la lección más importante del curso hasta ahora.

Contenido

  1. La sentencia if: tomar la primera decisión
  2. else: el camino alternativo
  3. elif: encadenar varias condiciones
  4. Condicionales anidados
  5. Condiciones compuestas con and, or y not
  6. Truthiness: valores que se comportan como True o False
  7. El operador ternario: condicionales en una línea

La sentencia if: tomar la primera decisión

La estructura básica de un condicional en Python es la sentencia if (en inglés, "si"). Su sintaxis es:

if condicion:
    # bloque que se ejecuta SOLO si la condición es verdadera
    instruccion_1
    instruccion_2

Fíjate en tres detalles fundamentales:

  • La condición es cualquier expresión que Python pueda evaluar como True o False (los booleanos que viste en el módulo 1).
  • Los dos puntos (:) al final de la línea del if son obligatorios. Olvidarlos es el error de sintaxis más frecuente al empezar.
  • El bloque indentado (con 4 espacios, como ya sabes por PEP 8) define qué instrucciones dependen del if. En Python la indentación no es estética: es la estructura del programa.

Vamos a resolver la primera pregunta que Ana se hace cada vez que alguien pide un libro en Papyrus: ¿hay stock?

titulo = "La Odisea"
stock = 4

if stock > 0:
    print(f"'{titulo}' está disponible ({stock} unidades).")

print("Consulta finalizada.")

Salida:

'La Odisea' está disponible (4 unidades).
Consulta finalizada.

¿Qué ha pasado exactamente?

  1. Python evalúa stock > 0. Como stock vale 4, la expresión da True.
  2. Al ser verdadera, se ejecuta el bloque indentado (el print del mensaje de disponibilidad).
  3. La última línea, print("Consulta finalizada."), no está indentada, así que no forma parte del if: se ejecuta siempre, haya o no stock.

Si cambias stock = 0 y vuelves a ejecutar, verás solo Consulta finalizada.: el bloque del if se salta por completo.

El flujo de un if, visto como diagrama

flowchart TD
    A[Inicio] --> B{stock > 0}
    B -- True --> C[Mostrar disponibilidad]
    B -- False --> D[Continuar]
    C --> D
    D --> E[Consulta finalizada]

El programa llega a una bifurcación, elige un camino según la condición y después ambos caminos vuelven a unirse.

else: el camino alternativo

Muchas veces no basta con "haz esto si se cumple": también quieres hacer otra cosa si no se cumple. Para eso existe else ("si no"):

titulo = "Hamlet"
stock = 0

if stock > 0:
    print(f"'{titulo}' está disponible ({stock} unidades).")
else:
    print(f"'{titulo}' está agotado. Ana debe reponerlo.")

Salida:

'Hamlet' está agotado. Ana debe reponerlo.

Reglas de else:

  • No lleva condición propia: se ejecuta cuando la condición del if es falsa.
  • Va al mismo nivel de indentación que su if, también con dos puntos.
  • Es opcional: un if puede ir perfectamente solo, como en el primer ejemplo.

Con if/else garantizas que exactamente uno de los dos bloques se ejecuta siempre.

elif: encadenar varias condiciones

¿Y si hay más de dos escenarios? Ana quiere clasificar el stock de cada libro en tres niveles: agotado, quedan pocas unidades, o stock suficiente. Para encadenar condiciones se usa elif (contracción de else if):

titulo = "El Quijote"
stock = 8

if stock == 0:
    print(f"'{titulo}': AGOTADO. Pedir al distribuidor.")
elif stock <= 3:
    print(f"'{titulo}': quedan pocas unidades ({stock}).")
else:
    print(f"'{titulo}': stock suficiente ({stock} unidades).")

Salida:

'El Quijote': stock suficiente (8 unidades).

Cómo lo evalúa Python, en orden y de arriba abajo:

  1. stock == 08 == 0 es False. Se salta ese bloque.
  2. stock <= 38 <= 3 es False. Se salta también.
  3. Ninguna condición se cumplió, así que se ejecuta el else.

Puntos clave de las cadenas if/elif/else:

  • Puedes poner tantos elif como necesites.
  • En cuanto una condición da True, se ejecuta su bloque y el resto de la cadena se ignora, aunque otras condiciones también fueran ciertas. El orden importa.
  • El else final es opcional, pero suele ser buena idea incluirlo como "caso por defecto".

Ese segundo punto merece un ejemplo. Observa qué pasa si ordenamos mal las condiciones:

stock = 0

# MAL ordenado: la condición amplia va primero
if stock <= 3:
    print("Quedan pocas unidades.")   # ¡Se ejecuta esto!
elif stock == 0:
    print("AGOTADO.")                 # Nunca se llega aquí con stock 0

Con stock = 0, la primera condición (0 <= 3) ya es cierta, así que el mensaje de "AGOTADO" jamás se mostrará. Regla práctica: coloca primero las condiciones más específicas y deja las más generales para el final.

Condicionales anidados

Un bloque if puede contener, a su vez, otro if. Es lo que llamamos anidamiento, y sirve para decisiones que dependen de una decisión anterior. En Papyrus: primero comprobamos si hay stock y, solo si lo hay, comprobamos si el cliente es socio para aplicarle el descuento.

titulo = "La Odisea"
precio = 12.50
stock = 4
es_socio = True          # Luis es socio de Papyrus
DESCUENTO_SOCIO = 0.05

if stock > 0:
    print(f"Vendiendo '{titulo}'...")
    if es_socio:
        precio_final = precio * (1 - DESCUENTO_SOCIO)
        print(f"Descuento de socio aplicado: {precio_final:.2f} €")
    else:
        precio_final = precio
        print(f"Precio sin descuento: {precio_final:.2f} €")
else:
    print(f"No se puede vender '{titulo}': sin stock.")

Salida:

Vendiendo 'La Odisea'...
Descuento de socio aplicado: 11.88 €

Observa la indentación: el if es_socio: está indentado 4 espacios (dentro del primer if), y sus bloques internos están a 8 espacios. Cada nivel de anidamiento añade 4 espacios.

Consejo de estilo: dos niveles de anidamiento se leen bien; tres empiezan a costar; cuatro o más suelen indicar que el código necesita reorganizarse (a menudo con condiciones compuestas, que vemos a continuación, o con funciones, que verás en el módulo 3).

Condiciones compuestas con and, or y not

Ya conoces los operadores lógicos del módulo 1. Su gran momento es precisamente este: combinar varias comprobaciones en una sola condición.

Operador Resultado Ejemplo Evalúa a
and True solo si ambas partes son True stock > 0 and es_socio True si hay stock y es socio
or True si al menos una parte es True stock == 0 or precio > 50 True si está agotado o es caro
not Invierte el valor not es_socio True si no es socio

Con and podemos reescribir el ejemplo anterior sin anidar, cuando solo nos interesa un caso concreto:

titulo = "La Odisea"
precio = 12.50
stock = 4
es_socio = True
DESCUENTO_SOCIO = 0.05

if stock > 0 and es_socio:
    precio_final = precio * (1 - DESCUENTO_SOCIO)
    print(f"Venta a socio: '{titulo}' por {precio_final:.2f} €")
elif stock > 0:
    print(f"Venta normal: '{titulo}' por {precio:.2f} €")
else:
    print(f"'{titulo}' está agotado.")

Y con or, Ana puede detectar libros que requieren su atención por cualquiera de dos motivos:

stock = 2
precio = 15.90

if stock <= 3 or precio > 15:
    print("Libro marcado para revisión de Ana.")

Dos detalles importantes de los operadores lógicos en condiciones:

  • Evaluación en cortocircuito: en a and b, si a es False, Python ni siquiera evalúa b (el resultado ya no puede ser True). En a or b, si a es True, no evalúa b. Esto se aprovecha para escribir condiciones seguras, como if stock > 0 and 10 / stock < 3: — la división nunca se ejecuta si stock es 0.
  • Encadenado de comparaciones: Python permite escribir if 1 <= stock <= 3: en lugar de if stock >= 1 and stock <= 3:. Ambas son equivalentes, pero la primera es más legible y muy idiomática.

Cuando una condición compuesta mezcla and y or, usa paréntesis para dejar clara la intención (recuerda que and tiene prioridad sobre or):

# ¿Aplica promoción? Socios, o compras caras de clásicos
if es_socio or (precio > 15 and es_clasico):
    ...

Truthiness: valores que se comportan como True o False

Hasta ahora nuestras condiciones eran comparaciones explícitas (stock > 0). Pero Python permite poner cualquier valor como condición, y lo convertirá automáticamente a booleano. A esta conversión implícita se la llama truthiness (algo así como "veracidad").

La regla es sencilla de recordar: lo vacío y lo nulo es falso; el resto, verdadero. Estos son los valores falsy (que evalúan a False) más habituales:

Valor Tipo ¿Por qué es falsy?
False bool Es el falso literal
0, 0.0 int, float El cero numérico
"" str Cadena vacía
None NoneType Ausencia de valor
[], (), {} colecciones Colecciones vacías (las verás en el módulo 4)

Todo lo demás es truthy: 1, -3, 0.01, "hola", " " (¡una cadena con un espacio no está vacía!), etc.

Puedes comprobarlo en el REPL con bool():

>>> bool(0)
False
>>> bool(4)
True
>>> bool("")
False
>>> bool("Papyrus")
True
>>> bool(None)
False

¿Para qué sirve en la práctica? Para escribir condiciones más naturales. Estas dos versiones son equivalentes, y la segunda es la idiomática en Python:

stock = 4

# Versión explícita
if stock > 0:
    print("Hay stock.")

# Versión idiomática usando truthiness
if stock:
    print("Hay stock.")

Y muy útil con input(), que como recordarás siempre devuelve str. Si el usuario pulsa Intro sin escribir nada, devuelve la cadena vacía "", que es falsy:

nombre = input("Nombre del cliente (Intro para omitir): ")

if not nombre:
    nombre = "Cliente anónimo"

print(f"Bienvenido a Papyrus, {nombre}.")

Aquí not nombre es True cuando nombre está vacío, así que asignamos un valor por defecto. Este patrón (comprobar si una entrada está vacía) es constante en programas reales.

Matiz: usa truthiness cuando la pregunta natural sea "¿hay algo aquí?" (¿hay texto?, ¿hay unidades?). Si la pregunta es sobre un valor concreto ("¿el stock es exactamente 0?", "¿la respuesta es 's'?"), la comparación explícita (==) comunica mejor la intención.

El operador ternario: condicionales en una línea

Cuando lo único que hace un if/else es elegir entre dos valores, Python ofrece una forma compacta llamada expresión condicional u operador ternario:

valor_si_true if condicion else valor_si_false

Compara la versión clásica con la ternaria para calcular el precio de Luis:

precio = 9.95            # Hamlet
es_socio = True
DESCUENTO_SOCIO = 0.05

# Versión clásica: 4 líneas
if es_socio:
    precio_final = precio * (1 - DESCUENTO_SOCIO)
else:
    precio_final = precio

# Versión ternaria: 1 línea, mismo resultado
precio_final = precio * (1 - DESCUENTO_SOCIO) if es_socio else precio

print(f"Precio final: {precio_final:.2f} €")

También brilla dentro de f-strings, por ejemplo para el ticket de Papyrus:

stock = 4
etiqueta = "disponible" if stock else "agotado"
print(f"La Odisea — {etiqueta}")

Reglas de uso del ternario:

  • Es una expresión: produce un valor, así que puedes asignarla, imprimirla o pasarla a una función. Un if normal es una sentencia y no produce valor.
  • Se lee "A si condición, si no B", que es casi lenguaje natural.
  • Úsalo solo para elecciones simples entre dos valores. Si necesitas ejecutar varias instrucciones, o anidar ternarios dentro de ternarios, vuelve al if/else clásico: la legibilidad manda.

Errores Comunes y Consejos

  • Olvidar los dos puntos al final de if, elif o else produce SyntaxError. Es el fallo número uno de todo principiante; revísalo antes que nada.
  • Confundir = con ==: if stock = 0: es un error de sintaxis. = asigna, == compara. Python te protege aquí negándose a ejecutarlo.
  • Indentación inconsistente: mezclar 4 espacios con tabuladores o con 3 espacios provoca IndentationError. Configura tu editor (VS Code lo hace por defecto) para insertar 4 espacios al pulsar Tab.
  • Ordenar mal los elif: como viste, si una condición amplia va antes que una específica, la específica nunca se ejecutará. Ordena de lo más concreto a lo más general.
  • Comparar floats con ==: por la imprecisión de los decimales que vimos en el módulo 1, 0.1 + 0.2 == 0.3 da False. Para dinero en condicionales, compara con un margen: abs(total - esperado) < 0.001.
  • if es_socio == True: funciona, pero es redundante: es_socio ya es un booleano. Escribe if es_socio: y, para el caso contrario, if not es_socio:.
  • Consejo: cuando una condición compuesta se vuelva difícil de leer, guárdala en una variable con nombre descriptivo: puede_comprar = stock > 0 and es_socio y luego if puede_comprar:. El código se autodocumenta.

Ejercicios

Ejercicio 1: clasificador de stock

Escribe un script nivel_stock.py que, dadas las variables titulo y stock, imprima:

  • "AGOTADO — pedir urgente" si el stock es 0.
  • "Stock bajo — reponer pronto" si está entre 1 y 3 (ambos incluidos).
  • "Stock correcto" si está entre 4 y 10.
  • "Exceso de stock — no pedir más" si es mayor que 10.

Pruébalo con los tres libros del catálogo: La Odisea (4), Hamlet (6) y El Quijote (8).

Ejercicio 2: precio final de una venta

Amplía venta_socio.py: dadas las variables precio, es_socio y stock, el script debe:

  1. Si no hay stock, imprimir "Venta imposible: sin stock" y nada más.
  2. Si hay stock, calcular el precio con IVA_LIBROS = 0.04 incluido.
  3. Aplicar además DESCUENTO_SOCIO = 0.05 sobre el precio base solo si el cliente es socio (el descuento se aplica antes del IVA).
  4. Imprimir el precio final con dos decimales.

Comprueba que para El Quijote (15.90 €) comprado por Luis (socio) el resultado es 15.71 €.

Ejercicio 3: validador de alta de libro

En ficha_libro.py prometimos validar la entrada. Da el primer paso: pide con input() el título de un libro y su precio. Usando truthiness y un ternario:

  • Si el título está vacío, imprime "Error: el título es obligatorio".
  • Si no, convierte el precio a float e imprime, en una sola f-string con ternario, "<título>: económico" si cuesta menos de 12 € o "<título>: premium" en caso contrario.

Soluciones

Solución 1:

titulo = "La Odisea"
stock = 4

if stock == 0:
    mensaje = "AGOTADO — pedir urgente"
elif stock <= 3:
    mensaje = "Stock bajo — reponer pronto"
elif stock <= 10:
    mensaje = "Stock correcto"
else:
    mensaje = "Exceso de stock — no pedir más"

print(f"{titulo}: {mensaje}")

Fíjate en que no hace falta escribir 1 <= stock <= 3 en el segundo caso: si llegamos a ese elif, ya sabemos que stock no es 0, así que basta con stock <= 3. Cada rama puede apoyarse en que las anteriores fallaron. Los tres libros del catálogo caen en "Stock correcto".

Solución 2:

IVA_LIBROS = 0.04
DESCUENTO_SOCIO = 0.05

precio = 15.90       # El Quijote
es_socio = True      # Luis
stock = 8

if stock == 0:
    print("Venta imposible: sin stock")
else:
    base = precio * (1 - DESCUENTO_SOCIO) if es_socio else precio
    precio_final = base * (1 + IVA_LIBROS)
    print(f"Precio final: {precio_final:.2f} €")

Cálculo paso a paso: 15.90 × 0.95 = 15.105 (descuento de socio) y 15.105 × 1.04 = 15.7092, que la f-string redondea a 15.71 €. El ternario resuelve en una línea la elección del precio base.

Solución 3:

titulo = input("Título del libro: ")

if not titulo:
    print("Error: el título es obligatorio")
else:
    precio = float(input("Precio (€): "))
    print(f"{titulo}: {'económico' if precio < 12 else 'premium'}")

not titulo es True cuando el usuario pulsa Intro sin escribir (cadena vacía, falsy). El ternario va dentro de la f-string, entre llaves, porque es una expresión y produce un valor. Nota: si el usuario escribe un precio no numérico, float() fallará con ValueError; aprenderemos a manejarlo con elegancia en el módulo 7.

Conclusión

Tus programas ya saben decidir. Has aprendido la sentencia if con sus compañeras elif y else, a anidar decisiones cuando una depende de otra, a combinar comprobaciones con and/or/not (incluido el cortocircuito), a aprovechar el truthiness de los valores vacíos y a condensar elecciones simples con el operador ternario. Papyrus ya puede responder a sus dos preguntas de negocio esenciales: si hay stock y si toca aplicar el descuento de socio.

Pero seguimos decidiendo libro a libro, con variables sueltas. Ana tiene un catálogo entero, y comprobar el stock de cada título copiando y pegando ifs no escala. Lo que necesitamos es repetir una operación sobre muchos elementos, y de eso trata exactamente la siguiente lección: los bucles for y while, con los que recorreremos el catálogo completo de Papyrus y sumaremos la caja del día en unas pocas líneas.

Curso de Programación en Python

Módulo 1: Introducción a Python

Módulo 2: Estructuras de Control

Módulo 3: Funciones y Módulos

Módulo 4: Estructuras de Datos

Módulo 5: Programación Orientada a Objetos

Módulo 6: Manejo de Archivos

Módulo 7: Manejo de Errores y Excepciones

Módulo 8: Temas Avanzados

Módulo 9: Pruebas y Depuración

Módulo 10: Desarrollo Web con Python

Módulo 11: Ciencia de Datos con Python

Módulo 12: Proyecto Final

© Copyright 2026. Todos los derechos reservados