Bucles en Python: for, while, break, continue y else explicados
- Por qué los bucles multiplican el poder de tu código
- El bucle for: iterar sobre cualquier secuencia
- range(): repetir N veces con control total
- enumerate(), zip() y dict.items()
- El bucle while: repetir mientras se cumpla una condición
- break y continue: controlar el flujo dentro del bucle
- El else de bucle: la joya oculta de Python
- Bucles infinitos: cuándo son útiles y cómo no quedarse atascado
- List comprehensions: bucles en una línea
- Programa completo: generador de tablas de multiplicar
- Errores clásicos con bucles
- Preguntas frecuentes
Si los condicionales dan al programa la capacidad de decidir, los bucles le dan la capacidad de perseverar. Repetir una operación cien veces, recorrer cada elemento de una lista, pedir datos al usuario hasta que introduzca algo válido: todo eso se hace con bucles. Es la herramienta que convierte dos líneas de código en algo que hace el trabajo de miles.
Python tiene dos estructuras de bucle: for, para iterar sobre secuencias, y while, para repetir mientras se cumpla una condición. Más break, continue y el sorprendente else de bucle, que confunde a todo el que viene de Java o C y luego no puede vivir sin él.
🔁 El bucle for: iterar sobre cualquier secuencia
El for de Python es más parecido al foreach de otros lenguajes que al for clásico de C. No trabaja con índices por defecto, trabaja directamente con los elementos de cualquier objeto iterable.
# Recorrer una lista
frutas = ["manzana", "pera", "naranja"]
for fruta in frutas:
print(fruta)
# manzana
# pera
# naranja
# Recorrer un string (carácter a carácter)
for letra in "Python":
print(letra, end=" ")
# P y t h o n
# Recorrer un diccionario (por defecto: claves)
edades = {"Ana": 28, "Luis": 34, "Marta": 22}
for nombre in edades:
print(nombre) # Ana Luis Marta
# Recorrer valores
for edad in edades.values():
print(edad) # 28 34 22
# Recorrer pares clave-valor
for nombre, edad in edades.items():
print(f"{nombre}: {edad}")
📏 range(): repetir N veces con control total
Cuando necesitas repetir algo un número determinado de veces, usas range(). Genera una secuencia de enteros de forma eficiente — no crea la lista en memoria, genera los números uno a uno.
# range(fin): de 0 a fin-1
for i in range(5):
print(i) # 0 1 2 3 4
# range(inicio, fin): de inicio a fin-1
for i in range(1, 6):
print(i) # 1 2 3 4 5
# range(inicio, fin, paso): con incremento
for i in range(0, 20, 5):
print(i) # 0 5 10 15
# Contar hacia atrás (paso negativo)
for i in range(10, 0, -1):
print(i) # 10 9 8 7 6 5 4 3 2 1
# range() no incluye nunca el fin:
list(range(5)) # [0, 1, 2, 3, 4]
list(range(1, 5)) # [1, 2, 3, 4]
range(1_000_000) no crea un millón de enteros en memoria. Genera cada número cuando lo necesita el bucle. Por eso puedes hacer for i in range(10**9): sin preocuparte por la memoria (aunque el tiempo sí que sería un problema).
🛠️ enumerate(), zip() y dict.items()
Python incluye funciones que hacen los bucles for más expresivos y eliminan errores comunes.
enumerate(): índice y valor a la vez
frutas = ["manzana", "pera", "naranja"]
# Forma amateur (propensa a errores de índice):
for i in range(len(frutas)):
print(i, frutas[i])
# Forma idiomática Python:
for i, fruta in enumerate(frutas):
print(i, fruta)
# 0 manzana
# 1 pera
# 2 naranja
# Empezar desde 1 en lugar de 0:
for i, fruta in enumerate(frutas, start=1):
print(f"{i}. {fruta}")
# 1. manzana
# 2. pera
# 3. naranja
zip(): iterar dos listas en paralelo
nombres = ["Ana", "Luis", "Marta"]
notas = [8.5, 6.0, 9.2]
for nombre, nota in zip(nombres, notas):
estado = "aprobado" if nota >= 5 else "suspenso"
print(f"{nombre}: {nota} ({estado})")
# Ana: 8.5 (aprobado)
# Luis: 6.0 (aprobado)
# Marta: 9.2 (aprobado)
# zip() se detiene con la lista más corta
# Para unir con la más larga: itertools.zip_longest()
Recorrer diccionario con .items()
precios = {"café": 1.50, "tostada": 2.20, "zumo": 2.80}
total = 0
for producto, precio in precios.items():
print(f" {producto:<12} {precio:>6.2f} €")
total += precio
print(f"{'TOTAL':<12} {total:>6.2f} €")
🔄 El bucle while: repetir mientras se cumpla una condición
El while evalúa su condición antes de cada iteración. Si es verdadera, ejecuta el bloque. Si es falsa desde el principio, no ejecuta nada. La clave: algo dentro del bucle debe modificar eventualmente la condición para que el bucle termine.
# Cuenta hacia arriba
n = 0
while n < 5:
print(n)
n += 1 # sin esto: bucle infinito
# 0 1 2 3 4
# Pedir número hasta que sea positivo
numero = -1
while numero <= 0:
numero = int(input("Introduce un número positivo: "))
print(f"Gracias, has introducido {numero}")
# Adivinar número
import random
secreto = random.randint(1, 100)
intentos = 0
while True:
intento = int(input("Tu número (1-100): "))
intentos += 1
if intento < secreto:
print("Más alto")
elif intento > secreto:
print("Más bajo")
else:
print(f"¡Correcto en {intentos} intentos!")
break
⚡ break y continue: controlar el flujo dentro del bucle
break interrumpe el bucle completamente y continúa con lo que hay después. continue salta el resto de la iteración actual y pasa a la siguiente, sin salir del bucle.
# break: salir al encontrar el primero que cumple
numeros = [4, 7, 2, 9, 1, 5, 8]
for n in numeros:
if n > 6:
print(f"Primer número mayor que 6: {n}")
break # sale del for
# → Primer número mayor que 6: 7
# continue: saltar elementos no deseados
for n in range(10):
if n % 2 == 0:
continue # salta los pares
print(n, end=" ")
# → 1 3 5 7 9
# Combinados: procesar solo los válidos y parar ante el primero inválido crítico
datos = [10, 25, -5, 30, 15]
for dato in datos:
if dato < 0:
print(f"Dato inválido: {dato}. Abortando.")
break
if dato > 20:
continue # procesar solo los <= 20
print(f"Procesando {dato}")
💎 El else de bucle: la joya oculta de Python
Aquí viene la sorpresa. Tanto for como while tienen una cláusula else opcional. El bloque else se ejecuta cuando el bucle termina de forma natural, es decir, sin que se haya ejecutado un break.
# Buscar un elemento — patrón clásico
usuarios = [
{"id": 1, "nombre": "Ana"},
{"id": 2, "nombre": "Luis"},
{"id": 3, "nombre": "Marta"},
]
id_buscado = 5
for usuario in usuarios:
if usuario["id"] == id_buscado:
print(f"Encontrado: {usuario['nombre']}")
break
else:
print(f"Usuario con id={id_buscado} no encontrado.")
# → Usuario con id=5 no encontrado.
# Sin el else, necesitarías una bandera:
encontrado = False
for usuario in usuarios:
if usuario["id"] == id_buscado:
encontrado = True
print(f"Encontrado: {usuario['nombre']}")
break
if not encontrado:
print("No encontrado.") # más verboso, misma lógica
El else también funciona con while:
intentos = 0
while intentos < 3:
pwd = input("Contraseña: ")
if pwd == "correcta":
print("Acceso concedido")
break
intentos += 1
else:
# Solo llega aquí si agotó los 3 intentos sin break
print("Demasiados intentos. Cuenta bloqueada.")
♾️ Bucles infinitos: cuándo son útiles y cómo no quedarse atascado
Un while True: es un bucle que en principio no termina nunca. Se usa deliberadamente cuando necesitas repetir algo indefinidamente hasta que algo externo lo interrumpa.
# Menú interactivo — patrón habitual
def mostrar_menu():
print("\n=== MENÚ ===")
print("1. Ver lista")
print("2. Añadir elemento")
print("3. Salir")
lista_tareas = []
while True:
mostrar_menu()
opcion = input("Elige (1-3): ").strip()
if opcion == "1":
if lista_tareas:
for i, tarea in enumerate(lista_tareas, 1):
print(f" {i}. {tarea}")
else:
print(" (lista vacía)")
elif opcion == "2":
nueva = input("Nueva tarea: ").strip()
if nueva:
lista_tareas.append(nueva)
print(f" Añadida: {nueva}")
elif opcion == "3":
print("Hasta luego.")
break # única salida del bucle
else:
print(" Opción no válida.")
break nunca se alcanza, el programa se quedará colgado. Para interrumpirlo en la terminal pulsa Ctrl+C. Esto lanza una excepción KeyboardInterrupt que puedes capturar si necesitas hacer limpieza antes de salir.
⚡ List comprehensions: bucles en una línea
Las list comprehensions son una sintaxis compacta para crear listas aplicando una transformación o un filtro a una secuencia existente. Son más legibles y normalmente más rápidas que el for equivalente.
# Bucle for clásico:
cuadrados = []
for n in range(1, 6):
cuadrados.append(n ** 2)
# [1, 4, 9, 16, 25]
# List comprehension equivalente:
cuadrados = [n ** 2 for n in range(1, 6)]
# [1, 4, 9, 16, 25]
# Con filtro (la parte if es opcional):
pares = [n for n in range(20) if n % 2 == 0]
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# Transformar strings:
nombres = ["ana", "luis", "marta"]
mayusculas = [n.capitalize() for n in nombres]
# ["Ana", "Luis", "Marta"]
# Filtrar y transformar a la vez:
notas_aprobadas = [n for n in [4, 7, 3, 9, 5, 2] if n >= 5]
# [7, 9, 5]
# Dict comprehension (mismo concepto para diccionarios):
cuadrados_dict = {n: n**2 for n in range(1, 6)}
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
🛠️ Programa completo: generador de tablas de multiplicar
def tabla_multiplicar(numero, hasta=10):
"""Genera e imprime la tabla de multiplicar de un número."""
print(f"\n Tabla del {numero}")
print(" " + "-" * 20)
for i in range(1, hasta + 1):
resultado = numero * i
print(f" {numero:2d} × {i:2d} = {resultado:3d}")
print()
def pedir_numero(mensaje, minimo=1, maximo=20):
"""Pide un número dentro de un rango con validación."""
while True:
try:
n = int(input(mensaje))
if minimo <= n <= maximo:
return n
print(f" Introduce un número entre {minimo} y {maximo}.")
except ValueError:
print(" Eso no es un número válido.")
# Programa principal
print("=== GENERADOR DE TABLAS ===\n")
while True:
print("Opciones:")
print(" 1. Ver una tabla")
print(" 2. Ver varias tablas")
print(" 3. Salir")
opcion = input("\nElige: ").strip()
if opcion == "1":
n = pedir_numero("¿Qué tabla? (1-20): ", 1, 20)
hasta = pedir_numero("¿Hasta qué número? (1-20): ", 1, 20)
tabla_multiplicar(n, hasta)
elif opcion == "2":
inicio = pedir_numero("Desde: ", 1, 20)
fin = pedir_numero("Hasta: ", inicio, 20)
for n in range(inicio, fin + 1):
tabla_multiplicar(n)
elif opcion == "3":
print("\nHasta luego.")
break
else:
print(" Opción no válida.\n")
🐛 Errores clásicos con bucles
1. Bucle infinito por olvidar actualizar la condición
n = 0
while n < 5:
print(n)
# falta: n += 1 → bucle infinito, Ctrl+C para salir
2. Modificar una lista mientras la iteras
numeros = [1, 2, 3, 4, 5]
# ❌ Peligroso: comportamiento inesperado
for n in numeros:
if n % 2 == 0:
numeros.remove(n) # modifica la lista durante la iteración
# ✅ Correcto: iterar sobre una copia
for n in numeros[:]: # numeros[:] es una copia
if n % 2 == 0:
numeros.remove(n)
# ✅ O mejor: list comprehension
numeros = [n for n in numeros if n % 2 != 0]
3. range() con el límite equivocado
elementos = ["a", "b", "c"]
# ❌ Da IndexError: el índice 3 no existe
for i in range(len(elementos) + 1):
print(elementos[i])
# ✅ Correcto:
for i in range(len(elementos)):
print(elementos[i])
# ✅ Mejor: usar enumerate o iterar directamente
for elem in elementos:
print(elem)
4. Confundir break con continue
for n in range(10):
if n == 5:
break # sale del bucle al llegar a 5 → imprime 0 1 2 3 4
# continue # saltaría el 5 y seguiría → imprime 0 1 2 3 4 6 7 8 9
✅ Resumen y próximos pasos
for itera sobre cualquier secuencia. range() genera rangos de enteros eficientemente. enumerate() y zip() son los compañeros naturales del for en Python idiomático. while repite mientras se cumpla una condición, y while True con break es el patrón estándar para menús y entrada de usuario. break sale del bucle, continue salta a la siguiente iteración. Y el else de bucle se ejecuta solo si no hubo break.
La siguiente lección: funciones — cómo organizar el código en bloques reutilizables. Con funciones y bucles juntos, ya puedes estructurar programas de verdad.
❓ Preguntas frecuentes
❓ Preguntas frecuentes sobre Bucles en Python: for, while, break, continue y else explicados
Las dudas más comunes respondidas de forma clara y directa.
💬 Foro de discusión
¿Tienes dudas sobre Bucles en Python: for, while, break, continue y else explicados? Comparte tu pregunta con la comunidad.
Todavía no hay mensajes. ¡Sé el primero en participar!