Historia de la pregunta:
La función enumerate() apareció en Python 2.3 y ahora es el método estándar para acceder simultáneamente al elemento y al índice del elemento al iterar sobre colecciones. Antes de la llegada de enumerate(), los programadores solían crear sus propios contadores o utilizaban la función range(len(sequence)), lo cual era inconveniente y poco legible.
Problema:
Un bucle for normal solo itera sobre valores. Para acceder al índice, a menudo se usa range(len(...)), lo que no funciona para todos los objetos iterables (por ejemplo, generadores, cadenas y tuplas de longitud variable, así como al aplicar filtrados). Esto lleva a errores y complica el código.
Solución:
enumerate() devuelve pares (índice, elemento), lo que permite obtener el índice del elemento actual incluso para colecciones no estándar o generadores filtrados. La función acepta un segundo argumento opcional: el valor inicial del contador.
Ejemplo de código:
words = ['apple', 'banana', 'cherry'] for idx, word in enumerate(words, 1): print(f"{idx}: {word}") # Salida: # 1: apple # 2: banana # 3: cherry
Características clave:
¿Por qué se utiliza enumerate en funciones en lugar de range(len(seq))?
Respuesta: range(len(seq)) solo funciona para secuencias con acceso por índice y no tiene en cuenta los cambios de longitud durante la iteración. Además, es menos legible y funciona más lentamente o no funciona en absoluto para generadores. enumerate() proporciona un acceso seguro a pares índice-valor para cualquier colección iterable.
Ejemplo de código:
# No funciona con generador: gen = (x for x in range(5)) for i in range(len(gen)): print(i) # Error: el generador no tiene longitud
¿Se puede usar enumerate para modificar elementos de una lista durante la iteración?
Respuesta: Sí, pero es necesario iterar sobre los índices para escribir los valores. De lo contrario, si solo se itera sobre los valores, se modificará una copia del objeto, no el original.
Ejemplo de código:
nums = [1, 2, 3] for idx, val in enumerate(nums): nums[idx] = val * 2 # nums = [2, 4, 6]
¿Qué devolverá enumerate si se le pasa un objeto que cambia durante la iteración?
Respuesta: Si la colección cambia durante la iteración (por ejemplo, se eliminan elementos), el comportamiento puede ser inesperado, ya que enumerate avanza a través de un iterador interno que puede desincronizarse. Por lo tanto, no se recomienda modificar la colección durante la iteración.
range(len(...)) para objetos sin longitud o para aquellos cuya longitud puede cambiar.Caso negativo
Un programador itera sobre una lista usando range(len(list)) y elimina elementos en el proceso. El resultado — los índices se desplazan y se omiten algunos elementos.
Ventajas:
Desventajas:
Caso positivo
Se utiliza enumerate(), formando una nueva lista de los elementos necesarios o modificando el valor por índice, pero el tamaño de la lista no cambia durante el ciclo.
Ventajas:
Desventajas: