Los bucles for en Python repiten un bloque de código para cada elemento de un iterable. Se utilizan para procesar listas, leer archivos, transformar datos, generar informes, validar registros y automatizar operaciones repetitivas.
A diferencia de otros lenguajes, el for de Python suele recorrer valores directamente en lugar de controlar un índice manual. Esto hace que muchos bucles sean más claros.
Primer bucle for
languages = ["Python", "JavaScript", "Go"]
for language in languages:
print(language)En cada iteración, language recibe el siguiente elemento. El bloque indentado se ejecuta una vez por valor.
La guía oficial del bucle for explica por qué Python recorre elementos en lugar de utilizar solamente contadores.
Qué es un iterable
Un iterable puede entregar valores uno a uno. Strings, listas, tuplas, sets, diccionarios, ranges, archivos y generadores son iterables:
for character in "Python":
print(character)
for number in (10, 20, 30):
print(number)Las guías de tuplas, sets y diccionarios explican las diferencias entre estas colecciones.
Utilizar range()
range() genera una secuencia de enteros sin construir una lista completa:
for number in range(5):
print(number)El resultado va de 0 a 4. El valor final queda excluido.
for number in range(1, 6):
print(number)
for number in range(0, 11, 2):
print(number)
for number in range(5, 0, -1):
print(number)La guía de range() en Python explica inicio, fin, paso y errores de límites.
Cuando necesitas un índice
Este código funciona, pero es más complejo de lo necesario:
names = ["Ava", "Noah", "Mia"]
for index in range(len(names)):
print(index, names[index])enumerate() ofrece posición y valor:
for index, name in enumerate(names, start=1):
print(index, name)La documentación oficial de enumerate() describe sus parámetros y el valor inicial.
Recorrer diccionarios
Un bucle sobre un diccionario devuelve las claves:
prices = {"coffee": 3.50, "tea": 2.80}
for product in prices:
print(product)Para obtener clave y valor utiliza items():
for product, price in prices.items():
print(f"{product}: ${price:.2f}")También existen keys() y values() cuando solo necesitas una parte.
Combinar colecciones con zip()
names = ["Ava", "Noah", "Mia"]
scores = [92, 85, 88]
for name, score in zip(names, scores):
print(f"{name}: {score}")zip() termina cuando se agota el iterable más corto. Cuando las longitudes deben coincidir, utiliza strict=True en versiones compatibles:
for name, score in zip(
names,
scores,
strict=True,
):
print(name, score)Detener con break
numbers = [4, 8, 15, 16, 23, 42]
target = 16
for number in numbers:
if number == target:
print("Encontrado")
breakbreak sale inmediatamente del bucle más cercano. Es útil cuando continuar ya no aporta trabajo.
Saltar con continue
values = [10, -3, 7, -1, 5]
for value in values:
if value < 0:
continue
print(value)continue pasa al siguiente elemento. Utilízalo con moderación para que el flujo no se vuelva difícil de seguir.
La cláusula else
El else de un bucle se ejecuta cuando este termina sin break:
users = ["ava", "noah", "mia"]
search = "liam"
for user in users:
if user == search:
print("Usuario encontrado")
break
else:
print("Usuario no encontrado")Este patrón resulta útil en búsquedas, aunque una función o any() puede ser más clara en ciertos casos.
Bucles anidados
for row in range(1, 4):
for column in range(1, 4):
print(f"({row}, {column})")Los bucles anidados aparecen en tablas, cuadrículas, matrices y comparaciones por pares. El trabajo total se multiplica, por lo que dos colecciones de tamaño n pueden producir aproximadamente n² operaciones.
Tabla de multiplicar
for number in range(1, 6):
print(f"Tabla del {number}")
for multiplier in range(1, 11):
result = number * multiplier
print(
f"{number} × {multiplier} = {result}"
)
print()Este ejercicio combina bucles anidados y salida formateada.
No modificar una colección durante el recorrido
Cambiar una lista o diccionario mientras se recorre puede omitir elementos o generar errores. Construye una colección nueva:
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = []
for number in numbers:
if number % 2 == 0:
even_numbers.append(number)Para eliminar claves, recorre una copia:
inventory = {
"mouse": 0,
"keyboard": 5,
"monitor": 0,
}
for product in list(inventory):
if inventory[product] == 0:
del inventory[product]List comprehensions
Una comprensión puede transformar o filtrar valores:
squares = [
number ** 2
for number in range(1, 6)
]
even_squares = [
number ** 2
for number in range(1, 11)
if number % 2 == 0
]Para lógica con varios pasos, excepciones o efectos secundarios, un bucle normal es más legible.
Recorrer archivos
Un archivo de texto entrega una línea por iteración:
with open("events.log", encoding="utf-8") as file:
for line_number, line in enumerate(file, start=1):
cleaned = line.rstrip()
print(line_number, cleaned)Este enfoque consume menos memoria porque no carga el archivo completo.
Proyecto: informe de notas
students = {
"Ava": [90, 86, 94],
"Noah": [72, 80, 77],
"Mia": [95, 91, 97],
}
for name, grades in students.items():
average = sum(grades) / len(grades)
if average >= 90:
level = "Excelente"
elif average >= 75:
level = "Bien"
else:
level = "Necesita mejorar"
print(
f"{name:<10} {average:5.1f} {level}"
)Este ejemplo combina diccionarios, listas, condiciones y f-strings.
Proyecto: detectar duplicados
values = ["A", "B", "C", "A", "D", "B"]
seen = set()
duplicates = set()
for value in values:
if value in seen:
duplicates.add(value)
else:
seen.add(value)
print(duplicates)Un set permite comprobar pertenencia de forma eficiente.
Procesar registros válidos
records = [
{"name": "Ava", "age": 29},
{"name": "", "age": 34},
{"name": "Mia", "age": -2},
{"name": "Noah", "age": 41},
]
valid_records = []
for record in records:
name = record.get("name", "").strip()
age = record.get("age")
if not name:
continue
if not isinstance(age, int) or age < 0:
continue
valid_records.append({
"name": name,
"age": age,
})
print(valid_records)Extraer lógica a funciones
Cuando el cuerpo crece, conviértelo en una función:
def is_valid_record(record):
name = record.get("name", "").strip()
age = record.get("age")
return (
bool(name)
and isinstance(age, int)
and age >= 0
)
valid_records = [
record
for record in records
if is_valid_record(record)
]La guía de funciones en Python explica cómo reducir la complejidad de los bucles.
Rendimiento
Los bucles son apropiados para lógica general. NumPy y Pandas pueden procesar grandes arrays numéricos de forma vectorizada. Los generadores también evitan almacenar todos los resultados:
squares = (
number ** 2
for number in range(1_000_000)
)
for square in squares:
if square > 100:
breakEscribe primero código correcto y legible. Optimiza después de medir.
Errores frecuentes
- Olvidar la indentación.
- Esperar que
range()incluya el final. - Usar índices cuando solo se necesitan valores.
- Modificar una colección durante el recorrido.
- Crear demasiados niveles de anidación.
- Suponer que
zip()avisa de longitudes diferentes. - Utilizar una comprensión para lógica compleja.
Conclusión
Los bucles for permiten procesar cualquier iterable de manera clara. Domina la iteración directa, range(), enumerate(), zip(), break, continue, diccionarios, archivos y comprensiones. Practica generando informes, filtrando registros y combinando colecciones.






