lunes, 19 de enero de 2026

Aprendiendo Python de 0 a experto - Condicionales e Iteración

Condicionales e Iteraciones en Python
Python // Control Flow

Condicionales e Iteración

Domina el flujo de ejecución: bifurcaciones, bucles y estructuras de control en Python

"¿Me podría decir, por favor, qué camino debo tomar desde aquí?" "Eso depende en gran medida de adónde quieras llegar." — Lewis Carroll, Alicia en el País de las Maravillas

En ciencias de la computación, el flujo de control es el orden en que las instrucciones individuales de un programa son ejecutadas o evaluadas. Las dos formas principales de controlar el flujo son la programación condicional (branching) y los bucles (looping). Juntas, permiten crear una variedad infinita de programas.

MÓDULO_01

Programación Condicional

La programación condicional es algo que hacemos cada momento del día. Consiste en evaluar condiciones y decidir qué acción tomar: si la luz está verde, puedo cruzar; si está lloviendo, llevaré paraguas; si llego tarde al trabajo, llamaré a mi jefe.

La Sentencia if

La herramienta principal para la programación condicional en Python es la sentencia if. Su función es evaluar una expresión y, basándose en el resultado, elegir qué parte del código ejecutar:

Flujo de Decisión if/else
Evaluar condición
True → Bloque if
|
False → Bloque else
conditional_basic.py
# Ejemplo básico de if
late = True
if late:
    print("¡Necesito llamar a mi jefe!")

# Con cláusula else
late = False
if late:
    print("¡Necesito llamar a mi jefe!")
else:
    print("No necesito llamar a mi jefe...")
python conditional_basic.py
No necesito llamar a mi jefe...
La sentencia if evalúa la expresión en un contexto booleano (como si llamara a bool(late)). Si el resultado es True, se ejecuta el bloque indentado después del if.

La Cláusula elif

A veces necesitas más de dos caminos para elegir. Veamos un calculador de impuestos donde el porcentaje depende de tu ingreso:

taxes.py
income = 15000

if income < 10000:
    tax_coefficient = 0.0   # Sin impuestos
elif income < 30000:
    tax_coefficient = 0.2   # 20%
elif income < 100000:
    tax_coefficient = 0.35  # 35%
else:
    tax_coefficient = 0.45  # 45%

print(f"Pagarás: ${income * tax_coefficient} en impuestos")
python taxes.py
Pagarás: $3000.0 en impuestos
Ingreso Coeficiente Impuesto
< $10,000 0% $0
$10,000 - $29,999 20% Variable
$30,000 - $99,999 35% Variable
≥ $100,000 45% Variable

El Operador Ternario

Cuando solo necesitas elegir entre dos valores según una condición, el operador ternario ofrece una sintaxis más concisa:

FORMA CLÁSICA
if order_total > 100:
    discount = 25
else:
    discount = 0
OPERADOR TERNARIO
discount = 25 if order_total > 100 else 0

Pattern Matching (match/case)

Introducido en Python 3.10, el structural pattern matching permite comparar un valor contra múltiples patrones de forma elegante:

match_example.py
day_number = 4

match day_number:
    case 1 | 2 | 3 | 4 | 5:
        print("Día laboral")
    case 6:
        print("Sábado")
    case 7:
        print("Domingo")
    case _:
        print(f"{day_number} no es un número válido")
python match_example.py
Día laboral
El patrón _ es un comodín (wildcard) que coincide con cualquier valor. Funciona como el else final y debe ser el último case.
MÓDULO_02

Bucles (Looping)

Los bucles permiten repetir la ejecución de un bloque de código más de una vez. Python ha destilado todos los constructos de bucle en solo dos: for y while.

FOR LOOP
Ideal para iterar sobre secuencias conocidas
WHILE LOOP
Perfecto cuando dependes de una condición
COMBINADOS
Junto con condicionales, crean programas complejos

El Bucle for

El bucle for se usa para iterar sobre una secuencia como una lista, tupla o colección de objetos:

simple_for.py
# Iterando sobre una lista
for number in [0, 1, 2, 3, 4]:
    print(number)

# Usando range() - más eficiente
for number in range(5):
    print(number)

La Función range()

La función range() genera secuencias de números. Acepta uno, dos o tres argumentos:

range_examples.py
# Un valor: de 0 hasta el valor (excluido)
list(range(10))
# → [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# Dos valores: start hasta stop (excluido)
list(range(3, 8))
# → [3, 4, 5, 6, 7]

# Tres valores: start, stop y step
list(range(-10, 10, 4))
# → [-10, -6, -2, 2, 6]

Iterando con enumerate()

Cuando necesitas tanto el índice como el valor, usa enumerate() en lugar de range(len(...)):

NO PYTHONIC
surnames = ["Rivest", "Shamir", "Adleman"]
for i in range(len(surnames)):
    print(i, surnames[i])
PYTHONIC
surnames = ["Rivest", "Shamir", "Adleman"]
for i, surname in enumerate(surnames):
    print(i, surname)

Iterando Múltiples Secuencias con zip()

La función zip() permite iterar sobre múltiples secuencias en paralelo:

zip_example.py
people = ["Nick", "Rick", "Roger", "Syd"]
ages = [23, 24, 23, 21]
instruments = ["Drums", "Keyboards", "Bass", "Guitar"]

for person, age, instrument in zip(people, ages, instruments):
    print(person, age, instrument)
python zip_example.py
Nick 23 Drums
Rick 24 Keyboards
Roger 23 Bass
Syd 21 Guitar

El Bucle while

El bucle while se ejecuta mientras una condición sea verdadera. Es ideal cuando no sabes cuántas iteraciones necesitarás:

binary_conversion.py
# Convertir decimal a binario
n = 39
remainders = []

while n > 0:
    n, remainder = divmod(n, 2)
    remainders.append(remainder)

remainders.reverse()
print(remainders)  # → [1, 0, 0, 1, 1, 1] = 39 en binario
Si la condición nunca se vuelve False, el bucle se convierte en un bucle infinito. Estos se usan intencionalmente para cosas como servidores que escuchan peticiones continuamente.
MÓDULO_03

Control de Flujo en Bucles

A veces necesitas alterar el flujo normal de un bucle. Python proporciona dos sentencias para esto: break para salir completamente del bucle, y continue para saltar a la siguiente iteración.

Break vs Continue
continue
→ Salta iteración actual
|
break
→ Sale del bucle

Usando continue

Supongamos que quieres aplicar un 20% de descuento solo a productos que expiran hoy:

discount.py
from datetime import date, timedelta

today = date.today()
tomorrow = today + timedelta(days=1)

products = [
    {"sku": "1", "expiration_date": today, "price": 100.0},
    {"sku": "2", "expiration_date": tomorrow, "price": 50},
    {"sku": "3", "expiration_date": today, "price": 20},
]

for product in products:
    print("Procesando sku", product["sku"])
    if product["expiration_date"] != today:
        continue  # Salta al siguiente producto
    product["price"] *= 0.8
    print("Sku", product["sku"], "precio ahora", product["price"])
python discount.py
Procesando sku 1
Sku 1 precio ahora 80.0
Procesando sku 2
Procesando sku 3
Sku 3 precio ahora 16.0

Usando break

Si necesitas encontrar el primer elemento que cumple una condición y luego detenerte:

find_any.py
items = [0, None, 0.0, True, 0, 7]
found = False

for item in items:
    print("escaneando item", item)
    if item:
        found = True
        break  # Sale del bucle completamente

if found:
    print("Al menos un item evalúa a True")
else:
    print("Todos los items evalúan a False")
python find_any.py
escaneando item 0
escaneando item None
escaneando item 0.0
escaneando item True
Al menos un item evalúa a True

La Cláusula else en Bucles

Python tiene una característica única: puedes agregar un else después de un bucle. El bloque else se ejecuta solo si el bucle no fue interrumpido por break:

for_else.py
class DriverException(Exception):
    pass

people = [("James", 17), ("Kirk", 9), ("Lars", 13), ("Robert", 8)]

for person, age in people:
    if age >= 18:
        driver = (person, age)
        break
else:
    # Se ejecuta solo si NO hubo break
    raise DriverException("Conductor no encontrado.")
Raymond Hettinger sugiere pensar en el else de un bucle como nobreak: "Si el bucle terminó sin break, entonces ejecuta este bloque".
MÓDULO_04

Expresiones de Asignación

Python 3.8 introdujo el operador walrus (:=) que permite asignar valores a variables dentro de expresiones, donde normalmente no se permitiría una asignación.

Walrus Operator :=
:=
← Se llama "walrus" porque parece ojos y colmillos de morsa

Simplificando Condiciones

SIN WALRUS
remainder = value % modulus
if remainder:
    print(f"Resto: {remainder}")
CON WALRUS
if (remainder := value % modulus):
    print(f"Resto: {remainder}")

Simplificando Bucles while

menu_walrus.py
flavors = ["pistacho", "malaga", "vainilla", "chocolate"]
prompt = "Elige tu sabor: "
print(flavors)

# El walrus asigna Y evalúa en la misma línea
while (choice := input(prompt)) not in flavors:
    print(f"Lo siento, '{choice}' no es una opción válida.")

print(f"Elegiste '{choice}'.")
Usa el operador walrus con moderación. Aunque puede hacer el código más conciso, el uso excesivo puede afectar la legibilidad. Siempre piensa primero en la claridad del código.
MÓDULO_05

Ejemplo Práctico: Generador de Primos

Combinemos todo lo aprendido para crear un generador de números primos. Un número primo es mayor que 1 y solo es divisible por 1 y por sí mismo.

primes.py
primes = []
upto = 100

for n in range(2, upto + 1):
    for divisor in range(2, n):
        if n % divisor == 0:
            break
    else:  # nobreak: n es primo
        primes.append(n)

print(primes)
python primes.py
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
El else del bucle interno se ejecuta solo si ningún divisor dividió exactamente a n (es decir, no hubo break). Esto indica que n es primo.

Lookup Tables: Aplicando Descuentos

En lugar de usar múltiples if/elif, una técnica elegante es usar diccionarios como tablas de búsqueda:

coupons_lookup.py
customers = [
    dict(id=1, total=200, coupon_code="F20"),
    dict(id=2, total=150, coupon_code="P30"),
    dict(id=3, total=100, coupon_code="P50"),
]

# Lookup table: (porcentaje, fijo)
discounts = {
    "F20": (0.0, 20.0),   # Fijo £20
    "P30": (0.3, 0.0),    # 30%
    "P50": (0.5, 0.0),    # 50%
    "F15": (0.0, 15.0),   # Fijo £15
}

for customer in customers:
    code = customer["coupon_code"]
    percent, fixed = discounts.get(code, (0.0, 0.0))
    customer["discount"] = percent * customer["total"] + fixed

for c in customers:
    print(c["id"], c["total"], c["discount"])
python coupons_lookup.py
1 200 20.0
2 150 45.0
3 100 50.0
MÓDULO_06

El Módulo itertools

El módulo itertools implementa bloques de construcción de iteradores inspirados en APL, Haskell y SML. Proporciona tres categorías de iteradores.

Iteradores Infinitos

infinite_iterator.py
from itertools import count

for n in count(5, 3):  # Empieza en 5, suma 3 cada vez
    if n > 20:
        break
    print(n, end=", ")
python infinite_iterator.py
5, 8, 11, 14, 17, 20,

Iteradores de Terminación Corta

compress_example.py
from itertools import compress

data = range(10)
even_selector = [1, 0] * 10
odd_selector = [0, 1] * 10

even_numbers = list(compress(data, even_selector))
odd_numbers = list(compress(data, odd_selector))

print("Pares:", even_numbers)
print("Impares:", odd_numbers)
python compress_example.py
Pares: [0, 2, 4, 6, 8]
Impares: [1, 3, 5, 7, 9]

Generadores Combinatorios

permutations_example.py
from itertools import permutations

print(list(permutations("ABC")))
# N elementos tienen N! permutaciones
# "ABC" tiene 3! = 6 permutaciones
python permutations_example.py
[('A', 'B', 'C'), ('A', 'C', 'B'), ('B', 'A', 'C'), ('B', 'C', 'A'), ('C', 'A', 'B'), ('C', 'B', 'A')]
¡Cuidado con las permutaciones! El número crece factorialmente. Para 10 elementos: 10! = 3,628,800 permutaciones.

Resumen del Capítulo

01 // Condicionales

if/elif/else para bifurcar la ejecución. Operador ternario para asignaciones condicionales simples. match/case para múltiples patrones.

02 // Bucle for

Itera sobre secuencias e iterables. Usa enumerate() para índices y zip() para múltiples secuencias en paralelo.

03 // Bucle while

Ejecuta mientras una condición sea verdadera. Ideal cuando no conoces el número de iteraciones de antemano.

04 // Control de Flujo

break sale del bucle, continue salta a la siguiente iteración. else en bucles se ejecuta si no hubo break.

05 // Walrus Operator

:= permite asignar y usar un valor en la misma expresión. Útil en condiciones de while e if.

06 // itertools

Módulo poderoso con iteradores infinitos, de terminación corta y combinatorios. Explóralo para soluciones elegantes.

Basado en "Learn Python Programming" 4th Edition // Fabrizio Romano & Heinrich Kruger

Chapter 3: Conditionals and Iteration