AulaML Python · C++
Python principiante · 40 min · Estructuras de control

Bucles: while, for y control de iteraciones

Repetir trabajo sin copiar código: contadores, acumuladores y las herramientas para salir a tiempo

Un bucle repite un bloque de instrucciones mientras se cumpla una condición o hasta agotar una colección. Aquí aprendes a escribir while y for, a controlar range, a usar break, continue y pass, a acumular resultados y a evitar los dos fallos clásicos: el bucle infinito y el error de un elemento.

Lección 2 de 2 del módulo
Al terminar esta lección podrás
  • Elegir entre while y for según el problema
  • Recorrer secuencias y rangos con la firma correcta de range
  • Controlar la iteración con break, continue y pass
  • Acumular totales y contar elementos sin perder inicializaciones
  • Detectar y corregir bucles infinitos y errores de un elemento

Antes necesitas: Condicionales: if, elif y else

En esta lección
  1. ¿Qué es un bucle?
  2. ¿Para qué sirven?
  3. ¿Cómo funciona por dentro?
  4. Sintaxis: `while`
  5. Sintaxis: `for` y `range`
  6. Control fino: `break`, `continue` y `pass`
  7. Ejemplo básico: total y promedio de ventas
  8. Ejemplo intermedio: bucles anidados
  9. Caso práctico: seguimiento de ventas mensuales
  10. Visualización: el acumulador paso a paso
  11. Errores comunes
  12. Buenas prácticas
  13. Ejercicios
  14. Soluciones explicadas
  15. Resumen
  16. Evaluación

Imagina que tienes que sumar las ventas de 40 000 filas de un archivo. Escribir 40 000 sumas es imposible; copiar y pegar la misma línea tampoco es programar. La solución es indicar el patrón una vez y pedirle a Python que lo repita: eso es un bucle.

Python ofrece dos herramientas. while repite mientras una condición siga siendo verdadera. for recorre los elementos de una colección y se detiene cuando no quedan. Saber cuál usar es la mitad del trabajo.

¿Qué es un bucle?

Un bucle es una estructura de control que ejecuta un bloque varias veces. Cada repetición se llama iteración. El bloque puede leer y modificar variables, y esas modificaciones son las que permiten que el bucle termine o que haga algo distinto en cada vuelta.

Piensa en lavar platos: repites «toma un plato, lávalo, déjalo en el escurridor» hasta que no queden platos. La condición de parada no es un número fijo, es un estado del mundo. Un while funciona exactamente así; un for se parece más a recorrer una lista de invitados y saludar a cada uno.

¿Para qué sirven?

Cualquier tarea repetitiva con un patrón es candidata a un bucle. En un proyecto real aparecen constantemente:

  • Procesar datos: recorrer las filas de un CSV y sumar una columna.
  • Calcular agregados: total, promedio, máximo o cuántas veces se cumple algo.
  • Buscar: detenerte en cuanto encuentras el primer valor negativo.
  • Generar secuencias: imprimir una tabla, contar del 1 al 10, avanzar de dos en dos.
  • Machine Learning: repetir el entrenamiento durante n_epocas y detenerlo si la pérdida deja de mejorar.

¿Cómo funciona por dentro?

En un while, Python evalúa la condición antes de cada vuelta. Si es verdadera, ejecuta el cuerpo y vuelve a la condición; si es falsa, sale y continúa con la línea siguiente. No hay un número máximo de vueltas: si la condición nunca se vuelve falsa, el programa se queda ahí.

En un for, Python pide elementos a un iterador hasta que se agota. No hay contador visible ni condición que escribir: la colección decide cuándo terminar. Cuando no quedan elementos, el iterador lanza internamente una señal de parada y el bucle acaba.

range no es una lista: es un objeto que genera números bajo demanda. Por eso range(1_000_000) no ocupa un millón de posiciones en memoria. Si necesitas verlo completo, conviértelo con list(...), pero para recorrerlo no hace falta.

Sintaxis: `while`

La forma es while condición: seguido de un bloque indentado. Antes del bucle debes inicializar las variables que la condición usa, y dentro debes actualizarlas; si no, la condición se queda congelada.

PYTHON retiros.py
saldo = 100
retiro = 30
meses = 0

while saldo >= retiro:
    saldo -= retiro
    meses += 1

print(meses, saldo)
  • La condición saldo >= retiro se evalúa antes de cada vuelta.
  • saldo -= retiro actualiza la variable que controla el final: sin esta línea el bucle sería infinito.
  • meses += 1 acumula cuántas veces se ejecutó el cuerpo.
  • Cuando el saldo queda en 10, la condición es falsa y el bucle sale.
  • El resultado es 3 10: tres retiros y diez soles restantes.

Sintaxis: `for` y `range`

La forma es for variable in iterable: y el bloque indentado. En cada vuelta, variable toma el siguiente elemento. range genera enteros y tiene tres formas: range(fin), range(inicio, fin) y range(inicio, fin, paso). El límite fin nunca se incluye.

PYTHON rangos.py
for i in range(1, 6):
    print(i, i ** 2)

print(list(range(5, 0, -2)))

La primera línea recorre 1, 2, 3, 4, 5: empieza en 1 y se detiene antes de 6. El cuerpo imprime cada número y su cuadrado, de 1 1 a 5 25. La última línea convierte a lista el rango 5, 3, 1, que usa paso negativo para contar hacia atrás. Si necesitaras incluir el 6, escribirías range(1, 7).

Recorrer del 1 al 5
Python
PYTHON for_range.py
for i in range(1, 6):
    print(i)
C++
CPP for_clasico.cpp
#include <iostream>

int main() {
    for (int i = 1; i <= 5; ++i) {
        std::cout << i << std::endl;
    }
    return 0;
}

En Python el final de `range` es exclusivo, por eso se escribe 6 para llegar a 5. En C++ el límite se escribe en la condición y suele ser inclusivo. Ese detalle provoca la mitad de los errores de un elemento cuando cambias de lenguaje.

Control fino: `break`, `continue` y `pass`

A veces no quieres esperar al final natural del bucle. break lo abandona por completo; continue salta al siguiente elemento sin ejecutar el resto del cuerpo; pass no hace nada y sirve como marcador cuando la sintaxis exige un bloque.

PYTHON pedidos.py
pedidos = [12, 0, 8, -1, 20]
validos = 0

for pedido in pedidos:
    if pedido < 0:
        break
    if pedido == 0:
        continue
    validos += 1

print(validos)

El 12 se cuenta, el 0 se salta con continue, el 8 se cuenta y el -1 corta todo con break. El 20 nunca se visita, así que validos termina en 2. Con continue en lugar de break, el -1 se saltaría y el 20 se contaría: el resultado sería 3.

Los bucles admiten un else que se ejecuta solo si el bucle terminó sin break. Es útil para búsquedas: si recorres una colección buscando algo y no lo encuentras, el else lo informa sin necesidad de una bandera extra.

PYTHON buscar.py
objetivo = 7

for n in [2, 3, 4, 6]:
    if n == objetivo:
        print("encontrado")
        break
else:
    print("no encontrado")

Ningún elemento es 7, el break no se ejecuta y por eso se imprime no encontrado. Si el objetivo fuera 4, se imprimiría encontrado y el else se saltaría. El else pertenece al for, no al if: su indentación está al mismo nivel que el for.

Ejemplo básico: total y promedio de ventas

El patrón del acumulador aparece en casi todos los análisis: una variable empieza en cero y crece dentro del bucle. Aquí se suma una lista de ventas y se calcula su promedio:

PYTHON ventas.py
ventas = [120, 80, 150, 90]

total = 0
for venta in ventas:
    total = total + venta

print(f"Total: {total}")
print(f"Promedio: {total / len(ventas)}")
  • ventas es la colección; el for la recorre de izquierda a derecha.
  • total = 0 es la inicialización: si la omites, total = total + venta falla con NameError en la primera vuelta.
  • total = total + venta también se escribe total += venta; suma el elemento actual al acumulado.
  • Al terminar, total vale 440 y len(ventas) es 4.
  • 440 / 4 da 110.0; la división con / produce float aunque el resultado sea exacto.

El bucle no imprime nada por sí mismo: solo construye el resultado. Imprimir dentro del bucle mostraría cuatro totales parciales, que a veces es útil para depurar pero no es lo que pide el problema. Separa el cálculo de la presentación.

Ejemplo intermedio: bucles anidados

Un bucle dentro de otro genera combinaciones: filas y columnas, alumnos y materias, productos y meses. El bucle interno se ejecuta completo por cada vuelta del externo.

PYTHON tabla.py
for fila in range(1, 4):
    linea = ""
    for columna in range(1, 4):
        linea += str(fila * columna) + " "
    print(linea)

El bucle externo da tres vueltas y el interno también: el cuerpo de la multiplicación se ejecuta 9 veces. En la primera fila, linea acumula 1 2 3 ; en la segunda, 2 4 6 ; en la tercera, 3 6 9 . linea se reinicia a cadena vacía en cada fila, y eso es lo que impide que las filas se mezclen.

Los anidados crecen rápido: dos bucles de 1 000 elementos producen un millón de iteraciones. Antes de anidar, pregúntate si basta un solo recorrido o una estructura auxiliar.

Caso práctico: seguimiento de ventas mensuales

Tienes las ventas de seis meses y una meta de 1 000. Necesitas el total, el promedio y cuántos meses superaron la meta. Un solo recorrido puede calcular las tres cosas a la vez:

PYTHON resumen_ventas.py
ventas = [1250, 980, 1420, 1100, 870, 1600]
meta = 1000

sobre_meta = 0
total = 0
for venta in ventas:
    total += venta
    if venta >= meta:
        sobre_meta += 1

promedio = total / len(ventas)
print(f"Total: {total}")
print(f"Promedio: {promedio:.2f}")
print(f"Meses sobre la meta: {sobre_meta}")

La suma da 7220 y el promedio 1203.33, porque 7220 / 6 es 1203.333... y el formato corta a dos decimales. Alcanzaron la meta enero, marzo, abril y junio: cuatro meses. El condicional vive dentro del bucle, así que se evalúa seis veces, una por venta. Esta combinación de bucle y condicional es el esqueleto de casi cualquier informe.

Visualización: el acumulador paso a paso

La traza recorre una lista de dos ventas. Observa cómo total conserva su valor entre vueltas y cómo venta cambia en cada iteración.

Ejecución visual ·Cómo crece un acumulador
1 / 7
1 ventas = [120, 80]
2 total = 0
3 for venta in ventas:
4 total += venta
5 print(total)
Se crea la lista con dos elementos.
Variables
ventas = [120, 80]
Salida
—

Avanza paso a paso: observa la línea resaltada, las variables y la salida.

Errores comunes

Mensaje o síntomaPor qué ocurreCómo se arregla
El programa no termina nuncaLa condición del while no cambiaActualiza la variable dentro del bucle o añade un break
NameError: name 'total' is not definedUsaste total += x sin inicializar totalEscribe total = 0 antes del bucle
TypeError: 'int' object is not iterableEscribiste for i in 5:Usa for i in range(5):
IndentationError: expected an indented blockEl cuerpo del bucle quedó al mismo nivelIndenta con 4 espacios
Falta o sobra una iteraciónConfundiste el final exclusivo de rangePara 1..5 usa range(1, 6)
El bucle infinito más común
Incorrecto
PYTHON Nunca termina
i = 1
while i <= 3:
    print(i)
Correcto
PYTHON Correcto
i = 1
while i <= 3:
    print(i)
    i += 1

En la versión incorrecta, `i` vale 1 para siempre y la condición nunca se vuelve falsa; la terminal se llena de unos hasta que interrumpes con `Ctrl+C`. La actualización debe estar dentro del bucle, no antes ni después.

Buenas prácticas

  • Usa for cuando conozcas la colección y while cuando la parada dependa de un estado.
  • Inicializa contadores y acumuladores justo antes del bucle, nunca dentro.
  • Evita modificar la colección que estás recorriendo: itera sobre una copia si hace falta.
  • Si el cuerpo supera las 15 líneas, extrae parte del trabajo a una función.
  • Desconfía de los anidados con colecciones grandes: la cantidad de vueltas se multiplica.
  • En un while, escribe la actualización en las primeras líneas del cuerpo para no olvidarla.

Ejercicios

Ejercicio 1

Suma de pares del 1 al 20

Suma todos los números pares entre 1 y 20 inclusive y muestra el total. El resultado debe ser 110. Resuélvelo con un for y un acumulador, sin escribir la lista a mano.
Pista

range acepta un paso: empieza en 2 y avanza de 2 en 2. Recuerda que el límite superior es exclusivo.

Ejercicio 2

Factorial con un bucle

Calcula el factorial de 6, es decir, 1 * 2 * 3 * 4 * 5 * 6, usando un for y una variable que empiece en 1. Muestra el resultado, que debe ser 720.
Pista

El acumulador de un producto se inicializa en 1, no en 0: cualquier cosa multiplicada por 0 da 0.

Completar código Completa el acumulador
total = 0

for numero in (1, 6):
    total  numero

print(total)

Necesitas generar del 1 al 5 y sumar cada número al total.

Soluciones explicadas

En la suma de pares, el paso 2 evita el if y reduce las iteraciones a la mitad. El límite 21 parece raro hasta que recuerdas que range excluye el final. Comprueba siempre el primer y el último valor de cada rango.

En el factorial, la inicialización en 1 es la decisión crítica. El mismo patrón sirve para productos, potencias acumuladas y probabilidades conjuntas. Si el problema pidiera el factorial de 0, el bucle no se ejecutaría y el resultado sería correctamente 1: el caso base queda cubierto por la inicialización.

Resumen

  • Un bucle repite un bloque; cada vuelta es una iteración.
  • while depende de una condición y exige inicializar y actualizar sus variables.
  • for recorre una colección y termina cuando el iterador se agota.
  • range(inicio, fin, paso) excluye el final; el paso puede ser negativo.
  • break sale del bucle, continue salta a la siguiente vuelta y pass no hace nada.
  • El else de un bucle se ejecuta solo si no hubo break.
  • Los acumuladores se inicializan antes del bucle: 0 para sumas, 1 para productos.
  • Los bucles anidados multiplican las iteraciones y deben usarse con cuidado.

Evaluación

Evaluación 1

¿Qué números produce range(2, 10, 3)?

Evaluación 2

¿Cuántas veces se ejecuta el cuerpo de for i in range(4):?

Evaluación 3

En for n in [1, 2, 3]: if n == 2: break, ¿qué ocurre?

Tus notas

¿Ya lo entendiste?

Márcala como completada para llevar tu progreso y desbloquear el siguiente paso de la ruta.