Fundamentos
El bucle for y la función range() en Python
Aprende el bucle for en Python con range() de uno, dos y tres argumentos, recorre textos y secuencias y evita las trampas del límite que no entra.
Por Prof. Rodrigo Faustino · Actualizado el · 13 min de lectura
Métricas de este artículo
- Palabras
- 2528
- Caracteres
- 13.226
- Tiempo de lectura
- ~13 min
El for recorre una secuencia de valores y ejecuta el bloque una vez por cada valor. Cuando el programa necesita repetir algo un número conocido de veces, la secuencia viene de la función range(): range(5) entrega los números 0, 1, 2, 3 y 4, y el bucle da cinco vueltas. El punto que más atrapa a quien empieza es que el límite nunca entra en la cuenta: range(1, 6) va de 1 hasta 5.
El artículo anterior mostró el while, en que la persona escribe el valor inicial, la prueba y la actualización. El for junta esas tres piezas en una sola línea y deja que Python se ocupe de ellas. Este artículo explica el range() con uno, dos y tres argumentos, muestra que el for sirve para textos y para grupos de valores, acompaña los usos más comunes (sumas, máximos, tablas) y lista los errores que aparecen en las clases.
Del while al for
Mira la tabla del 2 escrita con for:
for i in range(1, 6):
print("2 x", i, "=", 2 * i)
soma = 0
for n in range(1, 11):
soma = soma + n
print("suma de 1 a 10:", soma)
print(sum(range(1, 11)))La salida es la tabla de 2 x 1 = 2 a 2 x 5 = 10, después suma de 1 a 10: 55 y, en la última línea, 55 otra vez. La primera línea del bucle tiene la palabra for, el nombre de la variable que recibe cada valor (i), la palabra in, la secuencia (range(1, 6)) y los dos puntos. El bloque con sangría de abajo es el cuerpo. No hay i = 1 antes ni i += 1 adentro: el for toma el primer valor del range en la primera vuelta, el segundo en la segunda, y termina cuando los valores se acaban.
La segunda parte del ejemplo es el patrón del acumulador, visto en el artículo sobre por qué repetir: la variable soma empieza en 0 y recibe cada n. El resultado, 55, es el de la suma de los diez primeros números. La función sum() hace la misma cuenta de una vez, y vale conocerla, pero el bucle con acumulador es lo que se aprende primero porque el mismo diseño sirve para productos, conteos y máximos.
La elección entre los dos bucles sigue una regla simple. Usa for cuando el programa ya sabe qué recorrer: los números de 1 a 10, los elementos de un grupo, las letras de un texto. Usa while cuando el final depende de algo que solo aparece con el programa corriendo, como una respuesta escrita o una lectura de sensor.
Del programa al semestre planificado
- Plan de enseñanza y calendario montados solos
- Diario de clases listo para pegar en el SIGA
- Diapositivas y listas de ejercicios con solucionario
Versión Community gratis · Windows
La función range()
El range() tiene tres formas, y la figura muestra cada una en una recta numérica. Para ver los números que produce, el ejemplo los convierte en lista con list():
print(list(range(5)))
print(list(range(2, 8)))
print(list(range(10, 0, -3)))
print(list(range(0, 10, 3)))
print(list(range(5, 2)))
print(list(range(0)))
print(range(5))
print(len(range(0, 10, 3)))
print(3 in range(5), 5 in range(5))La salida tiene nueve líneas: [0, 1, 2, 3, 4], [2, 3, 4, 5, 6, 7], [10, 7, 4, 1], [0, 3, 6, 9], [], [], range(0, 5), 4 y True False. Las formas son:
range(parada)empieza en 0, avanza de 1 en 1 y se detiene antes de la parada.range(5)da 0, 1, 2, 3, 4.range(inicio, parada)empieza en el inicio.range(2, 8)da 2, 3, 4, 5, 6, 7.range(inicio, parada, paso)avanza depasoenpaso.range(0, 10, 3)da 0, 3, 6, 9, yrange(10, 0, -3), con paso negativo, cuenta hacia atrás: 10, 7, 4, 1.
Tres detalles aparecen en la salida. El primero es que range(5, 2) y range(0) están vacíos: un for sobre ellos no corre ninguna vez, y el programa sigue adelante sin error. Para contar hacia atrás hace falta un paso negativo, como en el range(10, 0, -3). El segundo es que print(range(5)) no muestra los números sino range(0, 5): el range es una descripción de la secuencia, y no una lista ya lista. El list() es lo que la arma. El tercero es que el len() y el in funcionan directamente sobre él.
El range no gasta memoria
Como el range guarda solo el inicio, la parada y el paso, y produce cada número cuando el bucle lo pide, sirve para secuencias enormes sin costo:
for i in range(1000000):
if i == 3:
break
print("paró en", i)
print(len(range(1000000)))La salida es paró en 3 y 1000000. El programa nunca construyó una lista de un millón de elementos. Esto importa en la ESP32, que tiene poca memoria: un bucle con range(10000) cuesta lo mismo que uno con range(10), mientras que una lista con diez mil números ocuparía una parte de la RAM de la placa. El break que aparece en el ejemplo sale del bucle antes del final, y es tema de un artículo más adelante.
La variable después del bucle
Después del for, la variable del bucle sigue existiendo y guarda el último valor que recibió:
for i in range(5):
print(i)
print("después, i vale", i)La salida es de 0 a 4 y después, i vale 4. El i vale 4, y no 5: el 5 nunca fue entregado al bucle. Por eso se dice que el range(5) hace cinco vueltas y el i llega a 4.
Contando hacia atrás y de paso en paso
El paso negativo hace la cuenta regresiva, y el paso mayor que 1 sirve para saltar valores, como los múltiplos de 5 o los ángulos de un servo:
for i in range(10, 0, -3):
print(i)
for i in reversed(range(3)):
print("rev", i)
for graus in range(0, 181, 45):
print(graus)La salida es 10, 7, 4, 1, después rev 2, rev 1, rev 0 y por último 0, 45, 90, 135, 180. La función reversed() es una segunda forma de invertir el range. Fíjate en el límite del último bucle: para que el 180 entre, la parada es 181, y ese tipo de ajuste "uno de más" es lo que más genera dudas.
Recorriendo textos y grupos
El for no necesita range(): recorre cualquier secuencia. Un texto entrega las letras, una tupla entrega los elementos:
for letra in "ESP32":
print(letra)
for dia in ("lun", "mar", "mie"):
print(dia)
for i in range(3):
for j in range(3):
print(i * j, end=" ")
print()La salida es E, S, P, 3 y 2, después lun, mar y mie y, al final, una cuadrícula de tres líneas: 0 0 0, 0 1 2 y 0 2 4. El tercer bucle es un for dentro de otro, y vale la misma regla del while: el de adentro corre completo en cada vuelta del de afuera. La cuadrícula muestra la tabla de multiplicar de 0 a 2.
Cuando se necesita el número de la vuelta junto con el valor, la función enumerate() entrega los dos:
for i, dia in enumerate(("lun", "mar", "mie")):
print(i, dia)
for i, dia in enumerate(("lun", "mar"), 1):
print(i, dia)
for a, b in ((1, 2), (3, 4)):
print(a + b)La salida es 0 lun, 1 mar, 2 mie, después 1 lun y 2 mar y, por último, 3 y 7. El enumerate numera a partir de 0, o a partir del número dado como segundo argumento (el 1 del segundo bucle). El tercer bucle muestra que el for puede separar un par en dos variables, a y b, en cada vuelta. El ejemplo usa tuplas porque las listas, con todos sus recursos, son tema de un artículo más adelante en la serie.
La IA que recuerda tu vida y vive en tu ordenador
- Memoria a largo plazo con la fuente de cada respuesta
- Funciona sin conexión: tus datos se quedan en tu PC
- Lee PDF, diapositivas, fotos y grabaciones de reuniones
Plan Esencial gratis para siempre
Los patrones de siempre, ahora con for
El acumulador, el contador y el máximo son los mismos de cualquier bucle. Con las lecturas de un sensor guardadas en una tupla, el programa calcula el promedio, halla el mayor valor y muestra cada posición:
leituras = (512, 530, 498, 505, 521)
soma = 0
for v in leituras:
soma = soma + v
print("promedio", soma / len(leituras))
maior = leituras[0]
for v in leituras:
if v > maior:
maior = v
print("mayor", maior)
for i in range(len(leituras)):
print(i, leituras[i])La salida es promedio 513.2, mayor 530 y cinco líneas de 0 512 a 4 521. El leituras[0] toma el elemento de posición 0, el primero, y el leituras[i] toma el de la posición i. Las posiciones empiezan en 0, lo que combina con el range(len(leituras)): va de 0 hasta el último índice, 4. El patrón del máximo empieza con el primer valor, y no con 0, porque así funciona también cuando todos los valores son negativos. Cuando solo interesa el valor, y no la posición, el primer estilo (for v in leituras) es más claro y más corto que el range(len(...)).
Salir antes o saltar una vuelta
Dos comandos cambian el ritmo del bucle: el break sale de él de una vez y el continue salta a la próxima vuelta.
for i in range(5):
if i == 3:
break
print(i)
for i in range(5):
if i % 2 == 0:
continue
print("impar", i)La salida es 0, 1, 2, después impar 1 e impar 3. En el primer bucle el break interrumpe todo cuando i llega a 3, y el 3 no se imprime. En el segundo, el continue abandona el resto del cuerpo cuando i es par y va a la vuelta siguiente, así que solo se imprimen los impares. Los detalles de break y continue quedan para el artículo dedicado a ellos.
Qué cambia en la ESP32
El for y el range son los mismos del Python del computador. El uso más común en hardware es barrer un rango de valores, como el brillo de un LED con PWM:
from machine import Pin, PWM
import time
led = PWM(Pin(2), freq=1000)
for duty in range(0, 1024, 256):
led.duty(duty)
print("duty", duty)
time.sleep_ms(100)
led.duty(0)
print("fin")La salida es duty 0, duty 256, duty 512, duty 768 y fin. El range(0, 1024, 256) da cuatro escalones de brillo, y el time.sleep_ms sostiene cada uno por un instante, para que se pueda ver el cambio. El artículo sobre PWM, LED, zumbador y servo explica el duty y el rango de valores; aquí lo que importa es que el paso del range ajusta la suavidad de la transición.
El range() solo acepta números enteros. Para valores decimales, la manera es calcular a partir del entero de la vuelta, y no sumar un paso decimal varias veces:
for i in range(0, 11, 5):
print(i / 10)
x = 0.0
for i in range(10):
x = x + 0.1
print(x, x == 1.0)La salida es 0.0, 0.5 y 1.0 en la primera parte, y 1.0000001 False en la segunda. La división i / 10 parte de un entero exacto y da 0,5 sin error. La suma de 0,1 diez veces acumula el error de redondeo del float de 32 bits: el resultado queda en 1.0000001 y la comparación con 1 falla. En el Python del computador, el float de 64 bits da 0.9999999999999999, también distinto de 1. El for con range evita el problema del bucle while con decimales, porque el número de vueltas es fijo, pero el valor acumulado aún carga el error.
Errores comunes y cómo reconocerlos
Las dos primeras tarjetas de la figura son errores de lógica que Python no acusa. range(1, 5) entrega 1, 2, 3 y 4, y quien quería hasta 5 pierde el último. range(5, 1) no entrega nada, y el bucle no corre, sin mensaje. Los dos siguientes dan error de verdad:
for i in range(2.5):
print(i)Traceback (most recent call last):
File "main.py", line 1, in <module>
TypeError: can't convert float to intLos mensajes del simulador (MicroPython) y del Python del computador difieren en la redacción:
| Error | Simulador (MicroPython) | Python en el computador |
|---|---|---|
range(2.5) | TypeError: can't convert float to int | TypeError: 'float' object cannot be interpreted as an integer |
range(1, 10, 0) | ValueError: zero step | ValueError: range() arg 3 must not be zero |
for i in 5: | TypeError: 'int' object isn't iterable | TypeError: 'int' object is not iterable |
falta el : en el for | SyntaxError: invalid syntax (línea 1) | SyntaxError: expected ':' |
| cuerpo sin sangría | SyntaxError: invalid syntax (línea 2) | IndentationError: expected an indented block after 'for' statement on line 1 |
"Iterable" quiere decir "algo que se puede recorrer", y un número suelto, como el 5 del for i in 5:, no lo es. Lo que el alumno quería era range(5).
En el aula: dónde suele tropezar el for
Los casos de abajo se repiten en los grupos que acaban de aprender el range.
El límite que no entra
Es el error número uno. El ejercicio pide los números de 1 a 10 y el programa muestra de 1 a 9, porque el alumno escribió range(1, 10). La frase que lo resuelve: el primer número del range entra, el segundo no. Para llegar hasta 10, la parada es 11.
Cambiar la i dentro del bucle
Algunos alumnos creen que sumar algo a la i dentro del cuerpo va a "saltar" vueltas. No salta:
for i in range(3):
print("antes", i)
i = i + 10
print("después", i)La salida es antes 0, después 10, antes 1, después 11, antes 2 y después 12. La i cambia dentro de la vuelta, pero en la vuelta siguiente el for toma el próximo valor del range e ignora el cambio. Para saltar valores, el camino es el paso del range; para un bucle que cambia su propio contador, el while.
Esperar una lista
El print(range(5)) muestra range(0, 5), y el alumno cree que algo se rompió. El list(range(5)) muestra los números.
Usar el for donde hacía falta el while
Un programa que pide notas hasta que el usuario escriba -1 no sabe cuántas vueltas dará, así que el range no se aplica. La pregunta de decisión es: ¿el número de vueltas se conoce antes de que el bucle empiece?
El nombre de la variable que se repite
En dos bucles anidados con la misma variable (for i dentro de for i), el de adentro sobrescribe el de afuera y el resultado confunde. Nombres distintos, como i y j, o nombres con sentido, como linha y coluna, evitan el problema. Cuando la variable del bucle no se usa en el cuerpo, la convención es llamarla _, como en for _ in range(3):, que repite tres veces sin necesitar el número.
La sangría y los dos puntos
Los errores de sintaxis del for son los mismos del if y del while: dos puntos olvidados y cuerpo sin sangría. El simulador dice solo invalid syntax y la línea. El artículo sobre if y else tiene la lista de errores de sangría.
Ejercicio: tabla de temperaturas
Convertir grados Celsius en Fahrenheit, de 0 a 100 de 25 en 25, con la fórmula F = C * 9 / 5 + 32. Es un ejercicio de range con paso, y la tabla muestra el bucle funcionando.
for c in range(0, 101, 25):
f = c * 9 / 5 + 32
print(c, "C =", f, "F")La salida tiene cinco líneas: 0 C = 32.0 F, 25 C = 77.0 F, 50 C = 122.0 F, 75 C = 167.0 F y 100 C = 212.0 F. El 101 es la parada que deja entrar al 100. La división con / devuelve float, y por eso los resultados aparecen con .0.
Para una versión interactiva, la tabla de multiplicar del número que la persona escriba usa el input() y el int() antes del bucle:
n = int(input("Tabla del: "))
for i in range(1, 11):
print(n, "x", i, "=", n * i)Con la entrada 5, la salida va de 5 x 1 = 5 a 5 x 10 = 50. El int() es el del artículo sobre conversión de tipos, y el bucle for solo empieza después de que el número fue leído.
Preguntas frecuentes
¿El range puede empezar en 1?
Puede: range(1, 11) va de 1 a 10. Sin el primer argumento, el range empieza en 0, y eso combina con la forma de numerar posiciones que usa Python.
¿El range acepta números negativos?
Acepta en el inicio, en la parada y en el paso. range(-3, 3) va de -3 a 2, y range(5, -1, -1) cuenta de 5 a 0.
¿Cómo hago un bucle de 0 a 1 de 0,1 en 0,1?
Usa range(0, 11) y divide cada valor entre 10, como en el ejemplo del i / 10. El range solo trabaja con enteros.
¿Cuál es la diferencia entre for i in range(len(x)) y for item in x?
El primero recorre las posiciones, y el segundo recorre los valores. Prefiere el segundo cuando la posición no sea necesaria.
¿El for puede tener else?
Puede, y el bloque del else corre cuando el bucle termina sin break. Es tema del artículo sobre break, continue y el else de los bucles.
Para continuar
La ruta Lógica con Python tiene los desafíos de for y range. La Tabla del 2 y la Suma de 1 a 10 son los más directos, los Pares de 1 a 10 y los Múltiplos de 5 piden el paso y el límite con cuidado. Si el while todavía es la primera idea que viene a la cabeza, relee el artículo El bucle while.
El próximo tema es el "hacer-mientras": cómo repetir un bloque que necesita correr al menos una vez, con while True y break, ya que Python no tiene un comando propio para eso.