Bucles en Python: for, while, break, continue y else explicados

📅 Actualizado en marzo 2026 📊 Nivel: Principiante ⏱️ 18 min de lectura

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}")
Vías de tren que se bifurcan y se cruzan entre sí en la niebla, en blanco y negro
Vías de tren que se ramifican en la niebla: cada iteración de un bucle recorre su propio camino, una y otra vez. Fuente: Pexels (licencia libre).

📏 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() es perezoso: 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}")
Infografía comparativa de bucles for y while en Python: sintaxis, casos de uso, enumerate, zip, range y patrones clave
Comparativa for vs while: cuándo usar cada uno, sintaxis, funciones auxiliares (range, enumerate, zip) y los patrones más habituales con ejemplos de código. Infografía: Ciberaula.

💎 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.")
Disco de vinilo girando en un tocadiscos con la aguja apoyada sobre los surcos
Un disco de vinilo girando: los surcos en espiral son el loop más literal que existe. Incluso en música, "loop" significa repetición controlada. Fuente: Pexels (licencia libre).

♾️ 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.")
⚠️ Bucle infinito accidental: Si olvidaste modificar la condición o el 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}
Infografía de break, continue y else en bucles Python con sintaxis, ejemplos y casos de uso
break (sale del bucle), continue (salta a la siguiente iteración) y else de bucle (se ejecuta solo si no hubo break). Con ejemplos y patrones reales. Infografía: Ciberaula.

🛠️ 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.

Usa for cuando conoces de antemano el conjunto de elementos a iterar: una lista, un rango, un diccionario. Usa while cuando no sabes cuántas iteraciones necesitarás y la repetición depende de que se cumpla una condición. En Python el for es más habitual porque range() cubre la mayoría de los casos de "repetir N veces". El while es la elección natural para pedir datos al usuario hasta que sean válidos, esperar a que algo cambie, o implementar algoritmos de búsqueda o convergencia.
range() genera una secuencia de enteros bajo demanda. Tiene tres formas: range(fin) genera de 0 a fin-1, range(inicio, fin) genera de inicio a fin-1, y range(inicio, fin, paso) genera con el incremento indicado. El fin siempre es excluido. El paso puede ser negativo para contar hacia atrás: range(10, 0, -1) genera 10 9 8 ... 1. range() no crea una lista en memoria, genera los números uno a uno, lo que lo hace eficiente incluso con rangos muy grandes.
Usa enumerate(). Devuelve pares (índice, valor) para cada elemento de la secuencia. La forma habitual es for i, valor in enumerate(lista). Por defecto el índice empieza en 0, pero puedes cambiar el inicio: enumerate(lista, start=1) empieza desde 1. Evita el patrón for i in range(len(lista)): valor = lista[i] que es menos idiomático y más propenso a errores.
Un bucle infinito es un while cuya condición nunca se vuelve False, o un while True explícito. Son útiles cuando necesitas repetir algo indefinidamente hasta que el usuario decida parar (menús, servidores, juegos). Para salir de forma controlada usas break cuando se cumple una condición de salida. Para interrumpir un bucle infinito accidental en la terminal, pulsa Ctrl+C.
Una list comprehension es una sintaxis compacta para crear listas a partir de bucles: [expresión for elemento in iterable if condición]. Es más legible y generalmente más rápida que el bucle for equivalente para transformar o filtrar colecciones. Úsalas cuando la lógica sea sencilla y quepa en una línea sin perder claridad. Si necesitas anidar lógica compleja, un bucle for normal es más legible.
El bloque else de un bucle (tanto for como while) se ejecuta cuando el bucle termina de forma natural, es decir, sin que se ejecutara un break. Es especialmente útil en patrones de búsqueda: si encuentras el elemento haces break y el else no corre; si terminas el bucle sin encontrarlo el else se ejecuta y puedes manejar el caso "no encontrado" limpiamente, sin necesitar una variable bandera booleana.
Valora este artículo

💬 Foro de discusión

¿Tienes dudas sobre Bucles en Python: for, while, break, continue y else explicados? Comparte tu pregunta con la comunidad.

¿Tienes cuenta? o comenta como invitado ↓

Todavía no hay mensajes. ¡Sé el primero en participar!