Bucles en Python: for y while – Guía completa 2025 [+Ejemplos]

Bucles for y while en python

Contenido

¿Qué son los bucles en programación?

Los bucles (también llamados iteraciones o loops) son estructuras que permiten ejecutar un bloque de código múltiples veces. Son fundamentales en programación porque automatizan tareas repetitivas y te permiten procesar colecciones de datos de forma eficiente.

Imagina que necesitas enviar un email a 1000 clientes. Sin bucles, tendrías que escribir el mismo código 1000 veces. Con un bucle, escribes el código una vez y lo ejecutas automáticamente tantas veces como necesites.

Python ofrece dos tipos principales de bucles:

  • Bucle for – itera sobre una secuencia (lista, tupla, string, range, etc.)
  • Bucle while – repite mientras una condición sea verdadera

Cada tipo tiene sus casos de uso específicos. En este artículo aprenderás cuándo y cómo usar cada uno, junto con técnicas avanzadas como bucles anidados, break, continue y else.


Bucle for en Python: sintaxis básica

El bucle for en Python está diseñado para iterar sobre secuencias. A diferencia de otros lenguajes donde for se basa en contadores, en Python el for recorre directamente los elementos de una colección.

Bucle for python

Sintaxis

for variable in iterable:
    # código que se ejecuta en cada iteración
    instruccion1
    instruccion2

Elementos clave:

  • variable – toma el valor de cada elemento en cada iteración
  • iterable – cualquier objeto que se pueda recorrer (lista, tupla, string, range, etc.)
  • Los dos puntos : son obligatorios
  • El bloque debe estar indentado (4 espacios según PEP 8)

Ejemplo básico – Iterar sobre una lista

>>> fruits = ["apple", "banana", "orange", "grape"]
>>> for fruit in fruits:
...     print(f"Me gusta la {fruit}")
Me gusta la apple
Me gusta la banana
Me gusta la orange
Me gusta la grape

Iterar sobre strings

Los strings son iterables carácter por carácter:

>>> word = "Python"
>>> for letter in word:
...     print(letter)
P
y
t
h
o
n

Caso real – Procesar lista de precios

Imaginemos que tenemos una tienda online y necesitamos aplicar un descuento del 20% a todos los productos para una promoción especial. Usando un bucle for, podemos procesar cada precio y calcular su valor con descuento:

>>> prices = [100, 250, 75, 500, 150]
>>> discounted_prices = []
>>> discount_rate = 0.20
>>> 
>>> for price in prices:
...     discounted = price * (1 - discount_rate)
...     discounted_prices.append(discounted)
...     print(f"Precio original: ${price} → Con descuento: ${discounted}")
Precio original: $100 → Con descuento: $80.0
Precio original: $250 → Con descuento: $200.0
Precio original: $75 → Con descuento: $60.0
Precio original: $500 → Con descuento: $400.0
Precio original: $150 → Con descuento: $120.0
>>> 
>>> print(f"Precios con descuento: {discounted_prices}")
Precios con descuento: [80.0, 200.0, 60.0, 400.0, 120.0]

Bucle for con range() en Python

La función range() genera una secuencia de números, siendo extremadamente útil cuando necesitas repetir código un número específico de veces o iterar con índices.

Las tres formas de range()

range(stop)              # De 0 hasta stop-1
range(start, stop)       # De start hasta stop-1
range(start, stop, step) # De start hasta stop-1, en pasos de step

Ejemplo básico – Contador del 1 al 10

>>> for number in range(1, 11):
...     print(f"Número: {number}")
Número: 1
Número: 2
Número: 3
Número: 4
Número: 5
Número: 6
Número: 7
Número: 8
Número: 9
Número: 10

Cuenta regresiva

>>> for count in range(10, 0, -1):
...     print(count)
>>> print("¡Despegue!")
10
9
8
7
6
5
4
3
2
1
¡Despegue!

Iterar con paso personalizado

>>> # Números pares del 0 al 20
>>> for even in range(0, 21, 2):
...     print(even, end=" ")
0 2 4 6 8 10 12 14 16 18 20

Caso real – Generador de tabla de multiplicar

Vamos a crear un programa que genere la tabla de multiplicar de cualquier número. Esto es útil para aplicaciones educativas o cuando necesitas mostrar relaciones matemáticas:

>>> number = 7
>>> print(f"Tabla del {number}:")
>>> for i in range(1, 11):
...     result = number * i
...     print(f"{number} x {i} = {result}")
Tabla del 7:
7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63
7 x 10 = 70

Bucle for con enumerate()

La función enumerate() permite obtener simultáneamente el índice y el valor de cada elemento mientras iteras. Es extremadamente útil cuando necesitas saber la posición del elemento.

range en python

Sintaxis

for index, value in enumerate(iterable, start=0):
    # código usando index y value

Ejemplo básico – Lista numerada

>>> tasks = ["Comprar leche", "Llamar al médico", "Hacer ejercicio"]
>>> for index, task in enumerate(tasks, start=1):
...     print(f"{index}. {task}")
1. Comprar leche
2. Llamar al médico
3. Hacer ejercicio

Caso real – Procesar archivo con números de línea

Cuando procesamos archivos de log o cualquier documento de texto, es muy útil tener el número de línea junto al contenido. Aquí simulamos la lectura de un archivo y mostramos cada línea con su número:

>>> lines = ["primera línea", "segunda línea", "tercera línea"]
>>> for line_number, content in enumerate(lines, start=1):
...     print(f"Línea {line_number}: {content.upper()}")
Línea 1: PRIMERA LÍNEA
Línea 2: SEGUNDA LÍNEA
Línea 3: TERCERA LÍNEA

Bucles for anidados en Python

Un bucle anidado es un bucle dentro de otro bucle. El bucle interior se ejecuta completamente por cada iteración del bucle exterior.

Sintaxis básica

for variable_exterior in iterable_exterior:
    for variable_interior in iterable_interior:
        # código que usa ambas variables

Ejemplo básico – Tabla de multiplicar completa

>>> for i in range(1, 4):
...     for j in range(1, 4):
...         result = i * j
...         print(f"{i} x {j} = {result}")
...     print("---")  # Separador
1 x 1 = 1
1 x 2 = 2
1 x 3 = 3
---
2 x 1 = 2
2 x 2 = 4
2 x 3 = 6
---
3 x 1 = 3
3 x 2 = 6
3 x 3 = 9
---

Caso real – Generar combinaciones de productos

En un e-commerce, necesitas saber todas las posibles combinaciones de un producto. Por ejemplo, una camiseta disponible en diferentes tallas y colores. Los bucles anidados son perfectos para generar todas estas variantes:

>>> sizes = ["S", "M", "L", "XL"]
>>> colors = ["Rojo", "Azul", "Negro"]
>>> 
>>> print("Combinaciones disponibles:")
>>> product_combinations = []
>>> for size in sizes:
...     for color in colors:
...         combination = f"{color} - Talla {size}"
...         product_combinations.append(combination)
...         print(f"- {combination}")
Combinaciones disponibles:
- Rojo - Talla S
- Azul - Talla S
- Negro - Talla S
- Rojo - Talla M
- Azul - Talla M
- Negro - Talla M
- Rojo - Talla L
- Azul - Talla L
- Negro - Talla L
- Rojo - Talla XL
- Azul - Talla XL
- Negro - Talla XL
>>> 
>>> print(f"\nTotal combinaciones: {len(product_combinations)}")
Total combinaciones: 12

Complejidad de bucles anidados

Importante: Los bucles anidados aumentan exponencialmente el número de operaciones. Un bucle de N elementos dentro de otro de M elementos ejecuta N × M operaciones (complejidad O(n²)).

>>> # Ejemplo de complejidad O(n²)
>>> numbers = [1, 2, 3, 4, 5]
>>> execution_count = 0
>>> 
>>> for i in numbers:
...     for j in numbers:
...         execution_count += 1
>>> 
>>> print(f"Elementos: {len(numbers)}")
>>> print(f"Ejecuciones: {execution_count}")
>>> print(f"Complejidad: {len(numbers)} x {len(numbers)} = {execution_count}")
Elementos: 5
Ejecuciones: 25
Complejidad: 5 x 5 = 25

List comprehensions: for en una línea

Las list comprehensions son una forma compacta y pythónica de crear listas usando un bucle for en una sola línea.

Sintaxis

nueva_lista = [expresion for elemento in iterable if condicion]

Ejemplo básico – Números al cuadrado

>>> # Forma tradicional
>>> squares = []
>>> for number in range(1, 6):
...     squares.append(number ** 2)
>>> squares
[1, 4, 9, 16, 25]
>>> 
>>> # Con list comprehension
>>> squares = [number ** 2 for number in range(1, 6)]
>>> squares
[1, 4, 9, 16, 25]

Con condición – Filtrar números pares

>>> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> even_numbers = [num for num in numbers if num % 2 == 0]
>>> even_numbers
[2, 4, 6, 8, 10]

Caso real – Procesar lista de precios

Las list comprehensions son perfectas para transformar datos. Aquí aplicamos un descuento condicional: 20% de descuento solo a productos que cuesten más de 100 euros:

>>> prices = [100, 250, 75, 500, 150]
>>> 
>>> # Aplicar 20% descuento solo a precios mayores a 100
>>> discounted = [price * 0.8 if price > 100 else price for price in prices]
>>> discounted
[100, 200.0, 75, 400.0, 120.0]

Cuándo NO usar list comprehensions

Evita list comprehensions cuando:

  • La lógica es compleja (más de 2-3 operaciones)
  • Reduces la legibilidad
  • Necesitas efectos secundarios (print, modificar variables externas)
# Malo (demasiado complejo)
result = [item.upper().strip().replace(" ", "_") for item in items if len(item) > 5 and item.startswith("a")]

# Mejor (usar bucle tradicional)
result = []
for item in items:
    if len(item) > 5 and item.startswith("a"):
        processed = item.upper().strip().replace(" ", "_")
        result.append(processed)

Bucle while en Python: sintaxis básica

El bucle while repite código mientras una condición sea verdadera. A diferencia del for que itera sobre una secuencia conocida, el while continúa hasta que la condición se vuelve falsa.

while en python

Sintaxis

while condicion:
    # código que se ejecuta mientras condicion sea True
    instruccion1
    instruccion2

Importante: Debes asegurarte de que la condición eventualmente se vuelva False, o tendrás un bucle infinito.

Ejemplo básico – Contador simple

>>> counter = 1
>>> while counter <= 5:
...     print(f"Contador: {counter}")
...     counter += 1
Contador: 1
Contador: 2
Contador: 3
Contador: 4
Contador: 5

Diferencia fundamental con for

>>> # FOR: sabemos cuántas iteraciones haremos
>>> for i in range(5):
...     print(f"Iteración {i}")
>>> 
>>> # WHILE: depende de una condición que puede cambiar
>>> user_input = ""
>>> while user_input != "salir":
...     user_input = input("Escribe 'salir' para terminar: ")
...     print(f"Escribiste: {user_input}")

Caso real – Validación de input de usuario

Los bucles while son ideales cuando no sabes cuántas veces necesitarás repetir algo. Aquí creamos un sistema de validación que sigue pidiendo una contraseña hasta que cumpla los requisitos mínimos:

>>> valid_input = False
>>> attempts = 0
>>> max_attempts = 3
>>> 
>>> while not valid_input and attempts < max_attempts:
...     password = input("Ingresa tu contraseña: ")
...     if len(password) >= 8:
...         print("Contraseña válida")
...         valid_input = True
...     else:
...         attempts += 1
...         remaining = max_attempts - attempts
...         print(f"Contraseña muy corta. Intentos restantes: {remaining}")
>>> 
>>> if not valid_input:
...     print("Máximo de intentos alcanzado")

for vs while: ¿cuál usar?

Elegir entre for y while es una de las decisiones más frecuentes al programar. Aquí está la guía definitiva:

Usa for cuando:

  1. Sabes cuántas iteraciones necesitas
   for i in range(10):  # Exactamente 10 veces
       print(i)
  1. Iteras sobre una colección conocida
   for product in products:  # Procesar todos los productos
       process(product)
  1. Usas índices secuenciales
   for index in range(len(items)):
       print(f"Item {index}: {items[index]}")

Usa while cuando:

  1. No sabes cuántas iteraciones necesitarás
   while user_wants_to_continue():  # Hasta que el usuario decida parar
       do_something()
  1. La condición de parada es compleja
   while connection_active and data_available and not error_occurred:
       process_data()
  1. Necesitas un bucle infinito con break interno
   while True:
       command = get_command()
       if command == "exit":
           break
       execute(command)

Tabla comparativa

Criterioforwhile
Iteraciones conocidas✓ Ideal✗ No recomendado
Iteraciones desconocidas✗ Difícil✓ Ideal
Iterar colecciones✓ Perfecto✗ Innecesario
Condiciones complejas✗ Limitado✓ Flexible
Bucles infinitos✗ No aplica✓ Posible
Legibilidad✓ Alta~ Media
Riesgo bucle infinito✗ Bajo✓ Alto

Caso comparativo – Mismo problema, dos enfoques

Encontrar el primer número divisible por 7 en una lista:

>>> numbers = [10, 15, 21, 28, 30, 35]
>>> 
>>> # Con for
>>> found = None
>>> for number in numbers:
...     if number % 7 == 0:
...         found = number
...         break
>>> print(f"Encontrado con for: {found}")
Encontrado con for: 21
>>> 
>>> # Con while
>>> index = 0
>>> found = None
>>> while index < len(numbers) and found is None:
...     if numbers[index] % 7 == 0:
...         found = numbers[index]
...     index += 1
>>> print(f"Encontrado con while: {found}")
Encontrado con while: 21

En este caso, for es más legible y pythónico.


break, continue y else en bucles

Python ofrece tres palabras clave para controlar el flujo dentro de los bucles: break, continue y else.

break y continue en python

break – Salir del bucle inmediatamente

>>> # Buscar elemento en lista
>>> items = ["apple", "banana", "orange", "grape"]
>>> search_item = "orange"
>>> 
>>> for item in items:
...     print(f"Revisando: {item}")
...     if item == search_item:
...         print(f"¡Encontrado! {item}")
...         break  # Sale del bucle inmediatamente
>>> else:
...     print("No encontrado")
Revisando: apple
Revisando: banana
Revisando: orange
¡Encontrado! orange

continue – Saltar a la siguiente iteración

>>> # Procesar solo números pares
>>> for number in range(1, 11):
...     if number % 2 != 0:
...         continue  # Salta números impares
...     print(f"Número par: {number}")
Número par: 2
Número par: 4
Número par: 6
Número par: 8
Número par: 10

else en bucles – Ejecutar si NO se usó break

Esta es una característica única de Python que muchos programadores desconocen:

>>> # Verificar si una lista contiene solo números positivos
>>> numbers = [5, 10, 15, 20]
>>> 
>>> for num in numbers:
...     if num < 0:
...         print("Encontrado número negativo")
...         break
... else:
...     print("Todos los números son positivos")
Todos los números son positivos

Caso real – Sistema de login con intentos limitados

>>> max_attempts = 3
>>> correct_password = "python123"
>>> 
>>> for attempt in range(1, max_attempts + 1):
...     password = input(f"Intento {attempt}/{max_attempts} - Contraseña: ")
...     if password == correct_password:
...         print("¡Acceso concedido!")
...         break
...     else:
...         remaining = max_attempts - attempt
...         if remaining > 0:
...             print(f"Contraseña incorrecta. {remaining} intentos restantes")
... else:
...     print("Máximo de intentos alcanzado. Cuenta bloqueada.")

Llevando los bucles al siguiente nivel

En el libro Python a fondo encontrarás patrones avanzados de bucles, optimización de rendimiento y técnicas profesionales para procesar grandes volúmenes de datos eficientemente.

Ver el libro


Bucles while con condiciones complejas

Los bucles while brillan cuando necesitas evaluar múltiples condiciones o condiciones que cambian dinámicamente.

Múltiples condiciones con and/or

>>> balance = 100
>>> attempts = 0
>>> max_attempts = 3
>>> withdrawal_successful = False
>>> 
>>> while balance > 0 and attempts < max_attempts and not withdrawal_successful:
...     amount = int(input("Cantidad a retirar: "))
...     if amount <= balance:
...         balance -= amount
...         print(f"Retiro exitoso. Balance: ${balance}")
...         withdrawal_successful = True
...     else:
...         attempts += 1
...         print(f"Fondos insuficientes. Intento {attempts}/{max_attempts}")
>>> 
>>> if not withdrawal_successful:
...     print("Operación cancelada")

Caso real – Juego de adivinanza

Vamos a crear un juego simple donde el usuario debe adivinar un número. Este es un ejemplo perfecto de cuándo usar while porque no sabemos cuántos intentos necesitará el jugador:

>>> import random
>>> secret_number = random.randint(1, 100)
>>> attempts = 0
>>> max_attempts = 7
>>> guessed = False
>>> 
>>> print("Adivina el número entre 1 y 100")
>>> 
>>> while attempts < max_attempts and not guessed:
...     guess = int(input(f"Intento {attempts + 1}/{max_attempts}: "))
...     attempts += 1
...     
...     if guess == secret_number:
...         print(f"¡Correcto! Lo adivinaste en {attempts} intentos")
...         guessed = True
...     elif guess < secret_number:
...         print("Muy bajo. Intenta con un número mayor")
...     else:
...         print("Muy alto. Intenta con un número menor")
>>> 
>>> if not guessed:
...     print(f"Se acabaron los intentos. El número era {secret_number}")

Bucle while infinito en Python

Un bucle while True: crea un bucle infinito intencionalmente. Es útil para servicios, menús interactivos o procesos que deben correr indefinidamente.

Sintaxis

while True:
    # código que se repite indefinidamente
    if condicion_de_salida:
        break  # Única forma de salir

Ejemplo básico – Menú de aplicación

>>> while True:
...     print("\n=== MENÚ ===")
...     print("1. Opción A")
...     print("2. Opción B")
...     print("3. Salir")
...     
...     choice = input("Selecciona una opción: ")
...     
...     if choice == "1":
...         print("Ejecutando opción A...")
...     elif choice == "2":
...         print("Ejecutando opción B...")
...     elif choice == "3":
...         print("¡Hasta luego!")
...         break
...     else:
...         print("Opción inválida")

Caso real – Servidor simple que escucha conexiones

Los bucles infinitos son útiles para servicios que deben estar siempre activos. Aquí simulamos un servidor que acepta conexiones hasta alcanzar un límite o recibir un comando de parada:

>>> # Simulación de un servidor
>>> active = True
>>> connection_count = 0
>>> max_connections = 5
>>> 
>>> while True:
...     # Simular espera de conexión
...     command = input("Comando (connect/stop): ")
...     
...     if command == "connect":
...         connection_count += 1
...         print(f"Cliente conectado. Total: {connection_count}")
...         
...         if connection_count >= max_connections:
...             print("Máximo de conexiones alcanzado")
...             break
...     elif command == "stop":
...         print(f"Servidor detenido. Total conexiones: {connection_count}")
...         break
...     else:
...         print("Comando no reconocido")

Cuándo usar while True

Usa while True para:

  • Menús interactivos de consola
  • Servicios que escuchan conexiones
  • Procesamiento continuo de eventos
  • Servidores o daemons

Evita while True cuando:

  • Puedas expresar la condición de parada claramente
  • Estés aprendiendo (fácil olvidar el break)
  • El bucle debe terminar con certeza

Bucles while anidados

Al igual que con for, puedes anidar bucles while, pero debes tener especial cuidado con las condiciones de salida.

Ejemplo básico – Menú con submenús

>>> main_menu_active = True
>>> 
>>> while main_menu_active:
...     print("\n=== MENÚ PRINCIPAL ===")
...     print("1. Configuración")
...     print("2. Salir")
...     
...     choice = input("Opción: ")
...     
...     if choice == "1":
...         config_menu_active = True
...         while config_menu_active:
...             print("\n--- Configuración ---")
...             print("a. Cambiar idioma")
...             print("b. Volver")
...             
...             sub_choice = input("Opción: ")
...             
...             if sub_choice == "a":
...                 print("Idioma cambiado")
...             elif sub_choice == "b":
...                 config_menu_active = False
...     elif choice == "2":
...         print("¡Adiós!")
...         main_menu_active = False

Advertencia: Los bucles while anidados son propensos a errores. Es fácil crear bucles infinitos accidentales. Considera usar funciones para organizar mejor el código.


Contador y acumulador en while

Dos patrones fundamentales al usar while son el contador y el acumulador.

Patrón contador

El patrón contador es fundamental cuando necesitas contar cuántos elementos cumplen cierta condición. Aquí contamos cuántos números de una lista son mayores a 10:

>>> numbers = [5, 12, 8, 15, 20, 3, 18]
>>> index = 0
>>> count_greater_than_10 = 0
>>> 
>>> while index < len(numbers):
...     if numbers[index] > 10:
...         count_greater_than_10 += 1
...     index += 1
>>> 
>>> print(f"Números mayores a 10: {count_greater_than_10}")
Números mayores a 10: 4

Patrón acumulador

El acumulador suma, multiplica o concatena valores progresivamente. Es esencial para calcular totales, promedios o construir strings. Aquí calculamos la suma total y el promedio de una lista de números:

>>> numbers = [10, 20, 30, 40, 50]
>>> index = 0
>>> total_sum = 0
>>> 
>>> while index < len(numbers):
...     total_sum += numbers[index]
...     index += 1
>>> 
>>> average = total_sum / len(numbers)
>>> print(f"Suma total: {total_sum}")
>>> print(f"Promedio: {average}")
Suma total: 150
Promedio: 30.0

Caso real – Calcular promedio de notas con validación

Combinando ambos patrones, creamos un programa que solicita notas al usuario, valida que estén en el rango correcto, y calcula el promedio final. Es un ejemplo perfecto de cómo usar while True con break:

>>> print("Ingresa notas (escribe -1 para terminar)")
>>> total = 0
>>> count = 0
>>> 
>>> while True:
...     grade = float(input("Nota: "))
...     
...     if grade == -1:
...         break
...     
...     if 0 <= grade <= 10:
...         total += grade
...         count += 1
...     else:
...         print("Nota inválida (debe estar entre 0 y 10)")
>>> 
>>> if count > 0:
...     average = total / count
...     print(f"\nNotas ingresadas: {count}")
...     print(f"Promedio: {average:.2f}")
... else:
...     print("No se ingresaron notas válidas")

Bucles for con diccionarios

Los diccionarios ofrecen tres formas de iteración: claves, valores o pares clave-valor.

Iterar sobre claves (por defecto)

>>> user_data = {
...     "name": "John",
...     "age": 30,
...     "city": "Madrid"
... }
>>> 
>>> for key in user_data:
...     print(f"Clave: {key}")
Clave: name
Clave: age
Clave: city

Iterar sobre valores con .values()

>>> prices = {
...     "laptop": 800,
...     "phone": 500,
...     "tablet": 300
... }
>>> 
>>> total = 0
>>> for price in prices.values():
...     total += price
>>> 
>>> print(f"Total: ${total}")
Total: $1600

Iterar sobre pares clave-valor con .items()

>>> inventory = {
...     "apples": 50,
...     "bananas": 30,
...     "oranges": 25
... }
>>> 
>>> for product, quantity in inventory.items():
...     print(f"{product.capitalize()}: {quantity} unidades")
Apples: 50 unidades
Bananas: 30 unidades
Oranges: 25 unidades

Caso real – Procesar inventario con alertas

Vamos a crear un sistema que revisa el inventario de una tienda y alerta sobre productos con stock bajo. Esto es típico en sistemas de gestión de inventario:

>>> inventory = {
...     "laptop": 5,
...     "mouse": 50,
...     "keyboard": 3,
...     "monitor": 15
... }
>>> 
>>> low_stock_threshold = 10
>>> low_stock_items = []
>>> 
>>> print("Estado del inventario:")
>>> for product, stock in inventory.items():
...     status = "⚠️ BAJO" if stock < low_stock_threshold else "✓ OK"
...     print(f"{product}: {stock} unidades - {status}")
...     
...     if stock < low_stock_threshold:
...         low_stock_items.append(product)
>>> 
>>> if low_stock_items:
...     print(f"\nAlerta: Reponer {', '.join(low_stock_items)}")
Estado del inventario:
laptop: 5 unidades - ⚠️ BAJO
mouse: 50 unidades - ✓ OK
keyboard: 3 unidades - ⚠️ BAJO
monitor: 15 unidades - ✓ OK

Alerta: Reponer laptop, keyboard

Casos de uso reales de bucles

Caso 1: Procesamiento de archivos línea por línea

Cuando trabajas con archivos de log, necesitas encontrar y contar errores rápidamente. Este patrón es muy común en análisis de logs y debugging de aplicaciones:

>>> # Simulación de lectura de archivo
>>> log_lines = [
...     "ERROR: Connection failed",
...     "INFO: Server started",
...     "ERROR: Database timeout",
...     "INFO: Request processed",
...     "ERROR: Invalid credentials"
... ]
>>> 
>>> error_count = 0
>>> errors = []
>>> 
>>> for line_number, line in enumerate(log_lines, start=1):
...     if "ERROR" in line:
...         error_count += 1
...         errors.append((line_number, line))
...         print(f"Línea {line_number}: {line}")
Línea 1: ERROR: Connection failed
Línea 3: ERROR: Database timeout
Línea 5: ERROR: Invalid credentials
>>> 
>>> print(f"\nTotal errores encontrados: {error_count}")
Total errores encontrados: 3

Caso 2: Validación de formulario con retry

En aplicaciones web, necesitas validar el input del usuario y darle múltiples oportunidades de corregirlo. Aquí creamos un validador de email con límite de intentos:

>>> def validate_email(email):
...     return "@" in email and "." in email
>>> 
>>> max_retries = 3
>>> attempt = 0
>>> valid_email = None
>>> 
>>> while attempt < max_retries and not valid_email:
...     email_input = input(f"Ingresa email (intento {attempt + 1}/{max_retries}): ")
...     
...     if validate_email(email_input):
...         valid_email = email_input
...         print(f"Email válido: {valid_email}")
...     else:
...         attempt += 1
...         if attempt < max_retries:
...             print("Email inválido. Intenta nuevamente.")
>>> 
>>> if not valid_email:
...     print("Máximo de intentos alcanzado")

Caso 3: Sistema de descuentos progresivos

Los sistemas de e-commerce suelen tener descuentos que se acumulan según diferentes criterios. Este ejemplo muestra cómo procesar pedidos aplicando múltiples reglas de descuento:

>>> orders = [
...     {"id": 1, "total": 150, "customer": "premium"},
...     {"id": 2, "total": 80, "customer": "regular"},
...     {"id": 3, "total": 300, "customer": "premium"},
...     {"id": 4, "total": 50, "customer": "regular"}
... ]
>>> 
>>> for order in orders:
...     discount = 0
...     
...     # Descuento por tipo de cliente
...     if order["customer"] == "premium":
...         discount += 0.15
...     
...     # Descuento adicional por monto
...     if order["total"] > 100:
...         discount += 0.10
...     
...     final_price = order["total"] * (1 - discount)
...     savings = order["total"] - final_price
...     
...     print(f"Pedido #{order['id']}")
...     print(f"  Cliente: {order['customer']}")
...     print(f"  Subtotal: ${order['total']}")
...     print(f"  Descuento: {discount * 100}%")
...     print(f"  Total: ${final_price:.2f}")
...     print(f"  Ahorras: ${savings:.2f}\n")
Pedido #1
  Cliente: premium
  Subtotal: $150
  Descuento: 25.0%
  Total: $112.50
  Ahorras: $37.50

Pedido #2
  Cliente: regular
  Subtotal: $80
  Descuento: 0.0%
  Total: $80.00
  Ahorras: $0.00

Pedido #3
  Cliente: premium
  Subtotal: $300
  Descuento: 25.0%
  Total: $225.00
  Ahorras: $75.00

Pedido #4
  Cliente: regular
  Subtotal: $50
  Descuento: 0.0%
  Total: $50.00
  Ahorras: $0.00

Caso 4: Búsqueda y filtrado de datos

Filtrar datos de catálogos o bases de datos es una operación muy frecuente. Aquí buscamos productos específicos que cumplan múltiples criterios:

>>> products = [
...     {"name": "Laptop", "price": 800, "category": "electronics", "stock": 5},
...     {"name": "Mouse", "price": 25, "category": "electronics", "stock": 50},
...     {"name": "Desk", "price": 200, "category": "furniture", "stock": 10},
...     {"name": "Chair", "price": 150, "category": "furniture", "stock": 0},
...     {"name": "Monitor", "price": 300, "category": "electronics", "stock": 15}
... ]
>>> 
>>> # Buscar productos de electrónica con stock disponible
>>> search_category = "electronics"
>>> available_products = []
>>> 
>>> for product in products:
...     if product["category"] == search_category and product["stock"] > 0:
...         available_products.append(product)
>>> 
>>> print(f"Productos de {search_category} disponibles:")
>>> for product in available_products:
...     print(f"- {product['name']}: ${product['price']} ({product['stock']} unidades)")
Productos de electronics disponibles:
- Laptop: $800 (5 unidades)
- Mouse: $25 (50 unidades)
- Monitor: $300 (15 unidades)

Errores comunes con bucles

Error 1: Bucle infinito accidental

# Incorrecto (la condición nunca cambia)
>>> counter = 0
>>> while counter < 5:
...     print(counter)
...     # Olvidaste incrementar counter!

# Correcto
>>> counter = 0
>>> while counter < 5:
...     print(counter)
...     counter += 1

Error 2: Modificar lista mientras iteras

# Incorrecto (puede causar comportamiento inesperado)
>>> numbers = [1, 2, 3, 4, 5]
>>> for num in numbers:
...     if num % 2 == 0:
...         numbers.remove(num)  # ¡No hagas esto!

# Correcto (itera sobre una copia)
>>> numbers = [1, 2, 3, 4, 5]
>>> for num in numbers[:]:  # [:] crea una copia
...     if num % 2 == 0:
...         numbers.remove(num)
>>> numbers
[1, 3, 5]

# Mejor aún (usa list comprehension)
>>> numbers = [1, 2, 3, 4, 5]
>>> numbers = [num for num in numbers if num % 2 != 0]
>>> numbers
[1, 3, 5]

Error 3: Usar range con longitud incorrecta

# Incorrecto (IndexError)
>>> items = ["a", "b", "c"]
>>> for i in range(len(items) + 1):
...     print(items[i])
a
b
c
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
IndexError: list index out of range

# Correcto
>>> items = ["a", "b", "c"]
>>> for i in range(len(items)):
...     print(items[i])
a
b
c

# Mejor (pythónico)
>>> for item in items:
...     print(item)

Error 4: No inicializar acumuladores

# Incorrecto
>>> numbers = [1, 2, 3, 4, 5]
>>> for num in numbers:
...     total += num  # NameError: total no está definido

# Correcto
>>> numbers = [1, 2, 3, 4, 5]
>>> total = 0  # Inicializar antes del bucle
>>> for num in numbers:
...     total += num
>>> total
15

Error 5: Confundir break y continue

>>> # break sale del bucle completamente
>>> for i in range(5):
...     if i == 3:
...         break
...     print(i)
0
1
2

>>> # continue salta a la siguiente iteración
>>> for i in range(5):
...     if i == 3:
...         continue
...     print(i)
0
1
2
4

Error 6: Índice fuera de rango en while

# Incorrecto
>>> items = ["a", "b", "c"]
>>> i = 0
>>> while i <= len(items):  # <= es incorrecto
...     print(items[i])
...     i += 1
a
b
c
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
IndexError: list index out of range

# Correcto
>>> items = ["a", "b", "c"]
>>> i = 0
>>> while i < len(items):  # < es correcto
...     print(items[i])
...     i += 1
a
b
c

Optimización de bucles: mejores prácticas

1. Evita operaciones costosas dentro del bucle

Cada operación dentro de un bucle se ejecuta múltiples veces. Si calculas algo que no cambia en cada iteración, hazlo una sola vez antes del bucle para mejorar significativamente el rendimiento:

# Malo (calcula len() en cada iteración)
>>> items = list(range(1000))
>>> i = 0
>>> while i < len(items):
...     process(items[i])
...     i += 1

# Mejor (calcula len() una sola vez)
>>> items = list(range(1000))
>>> length = len(items)
>>> i = 0
>>> while i < length:
...     process(items[i])
...     i += 1

# Mejor aún (usa for, más pythónico)
>>> items = list(range(1000))
>>> for item in items:
...     process(item)

2. Usa comprensiones cuando sea apropiado

Las list comprehensions están optimizadas internamente en Python y son más rápidas que bucles for tradicionales para operaciones simples:

# Menos eficiente
>>> squares = []
>>> for i in range(100):
...     squares.append(i ** 2)

# Más eficiente
>>> squares = [i ** 2 for i in range(100)]

3. Break temprano cuando sea posible

Si estás buscando algo en una colección, sal del bucle tan pronto lo encuentres. No tiene sentido seguir iterando si ya tienes lo que necesitas:

# Menos eficiente (sigue iterando innecesariamente)
>>> found = None
>>> for item in large_list:
...     if item == target:
...         found = item

# Más eficiente (sale en cuanto encuentra)
>>> found = None
>>> for item in large_list:
...     if item == target:
...         found = item
...         break

4. Considera usar funciones built-in

Python tiene funciones optimizadas en C que son mucho más rápidas que escribir bucles manualmente. Usa sum(), max(), min(), any(), all() cuando sea posible:

# Menos eficiente
>>> numbers = [1, 2, 3, 4, 5]
>>> total = 0
>>> for num in numbers:
...     total += num

# Más eficiente (optimizado en C)
>>> numbers = [1, 2, 3, 4, 5]
>>> total = sum(numbers)

5. Evita concatenación de strings en bucles

Concatenar strings con += crea un nuevo objeto string en cada iteración, lo cual es muy ineficiente. Usa join() para unir múltiples strings:

# Muy ineficiente (crea nuevo string en cada iteración)
>>> result = ""
>>> for i in range(1000):
...     result += str(i)

# Mucho más eficiente
>>> result = "".join(str(i) for i in range(1000))

Puntos clave para recordar

Los bucles son fundamentales para automatizar tareas repetitivas y procesar colecciones de datos. Dominar for y while te permite escribir código más eficiente y elegante.

Pepitas de conocimiento

  1. for para iterables conocidos – Usa for cuando sepas sobre qué iterar
  2. while para condiciones dinámicas – Usa while cuando la condición de parada no esté clara
  3. range() genera secuencias – Perfecto para contadores y rangos numéricos
  4. enumerate() da índice + valor – No necesitas contadores manuales
  5. break sale, continue salta – Controla el flujo dentro del bucle
  6. else después de bucles – Se ejecuta si NO se usó break
  7. List comprehensions son pythónicas – Pero solo para casos simples
  8. Evita modificar durante iteración – Itera sobre copias si necesitas modificar
  9. Cuidado con bucles infinitos – Asegura que la condición eventually cambie
  10. Inicializa acumuladores – Siempre inicializa variables antes del bucle
  11. while True con break – Útil para menús y servicios
  12. Bucles anidados = O(n²) – Ten cuidado con el rendimiento

Próximos pasos

Ahora que dominas los bucles y las condicionales, tienes todas las herramientas para controlar el flujo de ejecución de tus programas. El siguiente paso es aprender a manejar errores y excepciones para hacer tu código más robusto.


Siguiente paso: Manejo de excepciones en Python

Ya sabes controlar el flujo con condicionales y bucles. Ahora aprende a manejar errores como un profesional:

Try-except y excepciones en Python – Guía completa


¿Te ha gustado este artículo? Compártelo con otros pythonistas que estén aprendiendo a programar.

Déjanos un comentario con tus dudas sobre bucles o comparte los casos de uso más interesantes que hayas implementado.

Para profundizar más con patrones avanzados de bucles, optimización de rendimiento y técnicas profesionales, no te pierdas Python a fondo.

Compartir

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Información básica sobre protección de datos Ver más

  • Responsable: Oscar Ramirez.
  • Finalidad:  Moderar los comentarios.
  • Legitimación:  Por consentimiento del interesado.
  • Destinatarios y encargados de tratamiento: No se ceden o comunican datos a terceros para prestar este servicio. El Titular ha contratado los servicios de alojamiento web a ionos (1&1) que actúa como encargado de tratamiento.
  • Derechos: Acceder, rectificar y suprimir los datos.
  • Información Adicional: Puede consultar la información detallada en la Política de Privacidad.

Publicar un comentario

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para fines de afiliación y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Contiene enlaces a sitios web de terceros con políticas de privacidad ajenas que podrás aceptar o no cuando accedas a ellos. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Ver Política de cookies
Privacidad