¿Qué significa enumerate ()?

Respuestas:

513

La enumerate()función agrega un contador a un iterable.

Entonces, para cada elemento en cursor, se produce una tupla con (counter, element); el forbucle une eso a row_numbery row, respectivamente.

Manifestación:

>>> elements = ('foo', 'bar', 'baz')
>>> for elem in elements:
...     print elem
... 
foo
bar
baz
>>> for count, elem in enumerate(elements):
...     print count, elem
... 
0 foo
1 bar
2 baz

Por defecto, enumerate()comienza a contar en, 0pero si le das un segundo argumento entero, comenzará desde ese número:

>>> for count, elem in enumerate(elements, 42):
...     print count, elem
... 
42 foo
43 bar
44 baz

Si tuviera que volver a implementar enumerate()en Python, aquí hay dos formas de lograrlo; uno usa itertools.count()para hacer el conteo, el otro cuenta manualmente en una función de generador :

from itertools import count

def enumerate(it, start=0):
    # return an iterator that adds a counter to each element of it
    return zip(count(start), it)

y

def enumerate(it, start=0):
    count = start
    for elem in it:
        yield (count, elem)
        count += 1

La implementación real en C está más cerca de la última, con optimizaciones para reutilizar un único objeto de tupla para el for i, ...caso de desempaquetado común y usar un valor entero C estándar para el contador hasta que el contador se vuelva demasiado grande para evitar usar un objeto entero Python (que es ilimitado).

Martijn Pieters
fuente
92

Es una función integrada que devuelve un objeto que se puede iterar. Ver la documentación .

En resumen, recorre los elementos de un iterable (como una lista), así como un número de índice, combinado en una tupla:

for item in enumerate(["a", "b", "c"]):
    print item

huellas dactilares

(0, "a")
(1, "b")
(2, "c")

Es útil si desea recorrer una secuencia (u otra cosa iterable), y también desea tener un contador de índice disponible. Si desea que el contador comience desde algún otro valor (generalmente 1), puede darle eso como segundo argumento enumerate.

RemcoGerlich
fuente
1
si agrega una segunda variable, itementonces puede eliminar el paréntesis: D
Abdelouahab
2
Pedantic: es una función que devuelve un iterador, no un generador. Los generadores son una clase específica de funciones definidas por el usuario (que usan yield/ yield fromo expresiones generadoras, que implícitamente yield); enumerateNo es un generador. Para todos los propósitos relacionados con la escritura de patos, no hay diferencia, pero la verificación explícita de tipos y los documentos del lenguaje Python solo usan el término "generador" para un propósito, que no cubre enumerate.
ShadowRanger
22

Estoy leyendo un libro ( Effective Python ) de Brett Slatkin y muestra otra forma de iterar sobre una lista y también conoce el índice del elemento actual en la lista, pero sugiere que es mejor no usarlo y usarlo enumerate. Sé que preguntaste qué significa enumerar, pero cuando entendí lo siguiente, también entendí cómo enumeratehace que iterar sobre una lista conozca el índice del elemento actual más fácil (y más legible).

list_of_letters = ['a', 'b', 'c']
for i in range(len(list_of_letters)):
    letter = list_of_letters[i]
    print (i, letter)

El resultado es:

0 a
1 b
2 c

También solía hacer algo, incluso más tonto antes de leer sobre la enumeratefunción.

i = 0
for n in list_of_letters:
    print (i, n)
    i += 1

Produce la misma salida.

Pero con enumeratesolo tengo que escribir:

list_of_letters = ['a', 'b', 'c']
for i, letter in enumerate(list_of_letters):
    print (i, letter)
Dora
fuente
20

Como han mencionado otros usuarios, enumeratees un generador que agrega un índice incremental al lado de cada elemento de un iterable.

Así que si usted tiene algo que decir la lista l = ["test_1", "test_2", "test_3"], el list(enumerate(l))te dará algo como esto: [(0, 'test_1'), (1, 'test_2'), (2, 'test_3')].

Ahora, cuando esto es útil? Un posible caso de uso es cuando desea iterar sobre elementos y desea omitir un elemento específico que solo conoce su índice en la lista pero no su valor (porque su valor no se conoce en ese momento).

for index, value in enumerate(joint_values):
   if index == 3:
       continue

   # Do something with the other `value`

Por lo tanto, su código se lee mejor porque también podría hacer un ciclo for regular rangepero luego acceder a los elementos que necesita para indexarlos (es decir, joint_values[i])

Aunque otro usuario mencionó una implementación del enumerateuso zip, creo que una forma más pura (pero un poco más compleja) sin usar itertoolses la siguiente:

def enumerate(l, start=0):
    return zip(range(start, len(l) + start), l)

Ejemplo:

l = ["test_1", "test_2", "test_3"]
enumerate(l)
enumerate(l, 10)

Salida:

[(0, 'prueba_1'), (1, 'prueba_2'), (2, 'prueba_3')]

[(10, 'prueba_1'), (11, 'prueba_2'), (12, 'prueba_3')]

Como se menciona en los comentarios, este enfoque con rango no funcionará con iterables arbitrarios como lo hace la enumeratefunción original .

Rafael
fuente
La razón por la que la otra respuesta menciona itertoolses que surange enfoque solo funciona con contenedores. enumeratetrabaja con iterables arbitrarios; si desea iterar un archivo, for lineno, line in enumerate(myfile):funciona, pero no pudo hacerlo range(len(myfile))porque la longitud no se conoce hasta que alcanza EOF.
ShadowRanger
12

La función enumerar funciona de la siguiente manera:

doc = """I like movie. But I don't like the cast. The story is very nice"""
doc1 = doc.split('.')
for i in enumerate(doc1):
     print(i)

La salida es

(0, 'I like movie')
(1, " But I don't like the cast")
(2, ' The story is very nice')
Ashok Kumar Jayaraman
fuente