Muchos bucles necesitan utilizar al mismo tiempo un elemento y su posición. Un contador manual funciona, pero obliga a inicializar una variable, incrementarla y mantenerla sincronizada. La función integrada enumerate() en Python resuelve este patrón al emparejar cada valor de un iterable con un contador.
En esta guía aprenderás la sintaxis, el argumento start, el uso con listas, cadenas, diccionarios, archivos, generadores, zip() y comprensiones. También veremos cuándo un índice no es necesario.
Qué devuelve enumerate()
enumerate(iterable, start=0) devuelve un iterador. En cada vuelta produce una tupla con el contador y el siguiente valor.
lenguajes = ["Python", "JavaScript", "Go"]
for indice, lenguaje in enumerate(lenguajes):
print(indice, lenguaje)Salida:
0 Python
1 JavaScript
2 GoLa documentación oficial de enumerate() describe su comportamiento.
Por qué es mejor que un contador manual
indice = 0
for lenguaje in lenguajes:
print(indice, lenguaje)
indice += 1La versión con enumerate comunica mejor la intención y evita olvidar el incremento.
for indice, lenguaje in enumerate(lenguajes):
print(indice, lenguaje)Cuando no necesitas la posición, utiliza el bucle más simple:
for lenguaje in lenguajes:
print(lenguaje)Comenzar a contar en 1
tareas = ["Instalar Python", "Crear un archivo", "Ejecutar el programa"]
for numero, tarea in enumerate(tareas, start=1):
print(f"{numero}. {tarea}")El valor de start cambia el contador producido, pero no los índices reales de la lista.
Convertir enumerate en lista
pares = list(enumerate(["rojo", "verde", "azul"], start=1))
print(pares)
# [(1, 'rojo'), (2, 'verde'), (3, 'azul')]La conversión es útil para inspección o reutilización, pero el uso normal como iterador consume menos memoria.
Usar enumerate con cadenas y tuplas
for posicion, caracter in enumerate("Python", start=1):
print(posicion, caracter)coordenadas = (12.5, -3.2, 8.0)
for eje, valor in enumerate(coordenadas):
print(eje, valor)Cualquier iterable puede utilizarse, no solamente una lista.
Enumerar diccionarios
Un bucle directo sobre un diccionario produce claves. Usa items() para obtener claves y valores.
puntuaciones = {"Ana": 95, "Luis": 88, "Marta": 91}
for posicion, (nombre, puntos) in enumerate(
puntuaciones.items(),
start=1,
):
print(f"{posicion}. {nombre}: {puntos}")El número representa el orden de iteración, no un índice permanente del diccionario.
Enumerar líneas de un archivo
from pathlib import Path
ruta = Path("notas.txt")
with ruta.open("r", encoding="utf-8") as archivo:
for numero_linea, linea in enumerate(archivo, start=1):
print(f"{numero_linea:4}: {linea.rstrip()}")Este patrón es útil en validadores, analizadores y mensajes de error, y no necesita cargar todo el archivo en memoria.
Combinar enumerate con zip()
productos = ["Teclado", "Ratón", "Monitor"]
precios = [49.90, 24.50, 219.00]
for fila, (producto, precio) in enumerate(
zip(productos, precios),
start=1,
):
print(f"{fila}. {producto}: {precio:.2f}")zip() combina iterables y enumerate añade un número de fila. Con Python moderno puedes usar strict=True para detectar longitudes diferentes.
for fila, (producto, precio) in enumerate(
zip(productos, precios, strict=True),
start=1,
):
print(fila, producto, precio)Encontrar posiciones que cumplen una condición
temperaturas = [18, 22, 31, 27, 35]
posiciones_calientes = [
indice
for indice, valor in enumerate(temperaturas)
if valor >= 30
]
print(posiciones_calientes) # [2, 4]Actualizar valores por índice
nombres = [" ana", "LUIS ", " marta "]
for indice, nombre in enumerate(nombres):
nombres[indice] = nombre.strip().title()
print(nombres)Cuando se reemplazan todos los valores, una comprensión suele ser más clara:
nombres = [nombre.strip().title() for nombre in nombres]No eliminar elementos mientras recorres la lista
Este patrón puede saltarse valores porque los índices cambian:
numeros = [1, 2, 3, 4, 5, 6]
# Evita este patrón.
for indice, numero in enumerate(numeros):
if numero % 2 == 0:
numeros.pop(indice)Crea una lista filtrada:
numeros = [numero for numero in numeros if numero % 2 != 0]Usar enumerate con generadores
def leer_lotes():
yield [1, 2]
yield [3, 4]
yield [5]
for numero_lote, lote in enumerate(leer_lotes(), start=1):
print(f"Lote {numero_lote}: {lote}")Tanto el generador como enumerate producen valores bajo demanda.
El iterador se consume
iterador = enumerate(["a", "b", "c"])
print(list(iterador))
print(list(iterador)) # []Crea otro objeto enumerate cuando necesites una segunda pasada.
Proyecto práctico: informe de validación
def validar_usuario(usuario):
errores = []
if not usuario.get("nombre", "").strip():
errores.append("falta el nombre")
correo = usuario.get("correo", "")
if "@" not in correo:
errores.append("correo inválido")
edad = usuario.get("edad")
if not isinstance(edad, int) or edad < 0:
errores.append("edad inválida")
return errores
def crear_informe(usuarios):
informe = []
for numero_fila, usuario in enumerate(usuarios, start=1):
errores = validar_usuario(usuario)
if errores:
informe.append(
f"Fila {numero_fila}: {', '.join(errores)}"
)
return informe
usuarios = [
{"nombre": "Ana", "correo": "[email protected]", "edad": 29},
{"nombre": "", "correo": "direccion-incorrecta", "edad": -2},
{"nombre": "Marta", "correo": "[email protected]", "edad": 34},
]
for mensaje in crear_informe(usuarios):
print(mensaje)Crear un menú numerado
def mostrar_menu(opciones):
for numero, opcion in enumerate(opciones, start=1):
print(f"{numero}. {opcion}")
mostrar_menu(["Crear", "Listar", "Eliminar", "Salir"])Errores frecuentes
- Usar enumerate cuando el índice nunca se utiliza.
- Confundir el contador personalizado con el índice real.
- Desempaquetar incorrectamente elementos de un diccionario.
- Esperar que el iterador se reinicie después de consumirlo.
- Eliminar elementos mientras se recorre la misma lista.
- Usar
range(len(lista))cuando solo se necesita elemento y posición.
Conclusión
enumerate() elimina la administración manual de contadores y mantiene los bucles legibles. Usa start=1 para resultados orientados a personas y recuerda que el objeto devuelto es un iterador de una sola pasada.
La regla práctica es sencilla: un bucle normal cuando solo necesitas valores, enumerate cuando necesitas valores y posiciones, y un bucle por índices cuando el índice dirige realmente la operación.
Lecturas relacionadas
- Repasa índices, copias y modificaciones con la guía de listas en Python.
- Comprende mejor
items()y el acceso por claves con la guía de diccionarios en Python. - Aplica la numeración de líneas a archivos reales con la guía de pathlib en Python.
Más documentación oficial
El tutorial oficial de Python sobre técnicas de bucle muestra enumerate(), zip() y otras formas idiomáticas de recorrer colecciones.






