O que significa enumerate ()?

Respostas:

513

A enumerate()função adiciona um contador a um iterável.

Portanto, para cada elemento em cursor, uma tupla é produzida com (counter, element); o forloop vincula isso a row_numbere row, respectivamente.

Demo:

>>> 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 padrão, enumerate()começa a contar, 0mas se você der um segundo argumento inteiro, ele começará a partir desse número:

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

Se você fosse reimplementar enumerate()no Python, aqui estão duas maneiras de conseguir isso; um usando itertools.count()para fazer a contagem, o outro contando manualmente em uma função de gerador :

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)

e

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

A implementação real em C é mais próxima da última, com otimizações para reutilizar um único objeto de tupla para o for i, ...caso de descompactação comum e usando um valor inteiro C padrão para o contador até que o contador se torne muito grande para evitar o uso de um objeto inteiro Python (que é ilimitado).

Martijn Pieters
fonte
92

É uma função interna que retorna um objeto que pode ser repetido. Veja a documentação .

Em resumo, faz um loop sobre os elementos de um iterável (como uma lista), bem como um número de índice, combinado em uma tupla:

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

impressões

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

É útil se você deseja fazer um loop sobre uma sequência (ou outra coisa iterável) e também deseja ter um contador de índice disponível. Se você deseja que o contador comece com algum outro valor (geralmente 1), pode dar isso como segundo argumento para enumerate.

RemcoGerlich
fonte
1
se você adicionar uma segunda variável a item, poderá remover o parêntese: D
Abdelouahab
2
Pedantic: É uma função retornando um iterador, não um gerador. Geradores são uma classe específica de funções definidas pelo usuário (usando yield/ yield from, ou expressões geradoras, que implicitamente yield); enumeratenão é um gerador. Para todos os propósitos relacionados à digitação de patos, não há diferença, mas a verificação explícita de tipo e os documentos da linguagem Python usam apenas o termo "gerador" para um propósito, que não abrange enumerate.
ShadowRanger
22

Estou lendo um livro ( Effective Python ) de Brett Slatkin e ele mostra outra maneira de iterar sobre uma lista e também conhecer o índice do item atual na lista, mas ele sugere que é melhor não usá-lo e usá-lo enumerate. Eu sei que você perguntou o que enumerar significa, mas quando entendi o seguinte, também entendi como a enumerateiteração em uma lista é feita, ao mesmo tempo em que o índice do item atual é mais fácil (e mais legível).

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

A saída é:

0 a
1 b
2 c

Eu também costumava fazer algo ainda mais bobinho antes de ler sobre a enumeratefunção.

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

Produz a mesma saída.

Mas com enumerateeu só tenho que escrever:

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

Como outros usuários mencionaram, enumerateé um gerador que adiciona um índice incremental ao lado de cada item de um iterável.

Então, se você tem uma lista digamos l = ["test_1", "test_2", "test_3"], o list(enumerate(l))lhe dará algo como isto: [(0, 'test_1'), (1, 'test_2'), (2, 'test_3')].

Agora, quando isso é útil? Um possível caso de uso é quando você deseja iterar sobre os itens e deseja pular um item específico que apenas conhece seu índice na lista, mas não seu valor (porque seu valor não é conhecido no momento).

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

   # Do something with the other `value`

Portanto, seu código é melhor porque você também pode fazer um loop for regular, rangemas para acessar os itens necessários para indexá-los (por exemplo, joint_values[i]).

Embora outro usuário tenha mencionado uma implementação do enumerateuso zip, acho que uma maneira mais pura (mas um pouco mais complexa) sem usar itertoolsé a seguinte:

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

Exemplo:

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

Resultado:

[(0, 'teste_1'), (1, 'teste_2'), (2, 'teste_3')]

[(10, 'teste_1'), (11, 'teste_2'), (12, 'teste_3')]

Conforme mencionado nos comentários, essa abordagem com range não funcionará com iterables arbitrários como a enumeratefunção original .

Rafael
fonte
A razão pela qual a outra resposta menciona itertoolsé que sua rangeabordagem funciona apenas com contêineres. enumeratetrabalha com iterables arbitrários; se você deseja iterar um arquivo, for lineno, line in enumerate(myfile):funciona, mas não pôde fazê-lo range(len(myfile))porque o comprimento não é conhecido até atingir o EOF.
ShadowRanger
12

A função enumerar funciona da seguinte maneira:

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)

A saída é

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