Cosa significa enumerate ()?


Risposte:


513

La enumerate()funzione aggiunge un contatore a un iterabile.

Quindi per ogni elemento in cursor, viene prodotta una tupla con (counter, element); il forloop lo lega rispettivamente a row_numbere row.

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

Per impostazione predefinita, enumerate()inizia a contare 0ma se gli dai un secondo argomento intero, inizierà invece da quel numero:

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

Se dovessi implementare nuovamente enumerate()in Python, ecco due modi per raggiungerlo; uno usa itertools.count()per fare il conteggio, l'altro conta manualmente in una funzione di generatore :

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

L' implementazione effettiva in C è più vicina a quest'ultima, con ottimizzazioni per riutilizzare un singolo oggetto tupla per il for i, ...caso di disimballaggio comune e usando un valore intero C standard per il contatore fino a quando il contatore diventa troppo grande per evitare l'uso di un oggetto intero Python (che è senza limiti).


92

È una funzione incorporata che restituisce un oggetto che può essere ripetuto. Vedere la documentazione .

In breve, scorre sopra gli elementi di un iterabile (come un elenco), nonché un numero indice, combinati in una tupla:

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

stampe

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

È utile se si desidera eseguire il ciclo su una sequenza (o altra cosa iterabile) e si desidera anche disporre di un contatore dell'indice. Se vuoi che il contatore inizi da un altro valore (di solito 1), puoi fornirlo come secondo argomento enumerate.


1
se aggiungi una seconda variabile a item, puoi rimuovere la parentesi: D
Abdelouahab

2
Pedante: è una funzione che restituisce un iteratore, non un generatore. I generatori sono una classe specifica di funzioni definite dall'utente (usando yield/ yield from, o espressioni del generatore, che implicitamente yield); enumeratenon è un generatore. Per tutti gli scopi legati alla tipizzazione delle anatre non vi è alcuna differenza, ma il controllo esplicito dei tipi e i documenti del linguaggio Python usano il termine "generatore" per un solo scopo, che non copre enumerate.
ShadowRanger,

22

Sto leggendo un libro ( Effective Python ) di Brett Slatkin e mostra un altro modo per scorrere su un elenco e anche conoscere l'indice dell'elemento corrente nell'elenco, ma mi suggerisce che è meglio non usarlo e usarlo enumerateinvece. So che hai chiesto cosa significhi enumerare, ma quando ho capito quanto segue, ho anche capito come enumeraterendere iterare un elenco mentre conosco l'indice dell'elemento corrente più facile (e più leggibile).

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

L'output è:

0 a
1 b
2 c

Facevo anche qualcosa, ancor più sciocco prima di leggere la enumeratefunzione.

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

Produce lo stesso output.

Ma con enumeratedevo solo scrivere:

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

20

Come altri utenti hanno già detto, enumerateè un generatore che aggiunge un indice incrementale accanto a ciascun elemento di un iterabile.

Quindi, se avete un dire l'elenco l = ["test_1", "test_2", "test_3"], il list(enumerate(l))vi darà qualcosa di simile a questo: [(0, 'test_1'), (1, 'test_2'), (2, 'test_3')].

Ora, quando è utile? Un possibile caso d'uso è quando si desidera scorrere gli elementi e si desidera saltare un elemento specifico che si conosce solo il suo indice nell'elenco ma non il suo valore (perché il suo valore non è noto al momento).

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

   # Do something with the other `value`

Quindi il tuo codice si legge meglio perché potresti anche fare un ciclo regolare con rangema poi per accedere agli elementi che devi indicizzare (cioè, joint_values[i]).

Sebbene un altro utente abbia menzionato un'implementazione enumeratedell'utilizzo zip, penso che un modo più puro (ma leggermente più complesso) senza usare itertoolssia il seguente:

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

Esempio:

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

Produzione:

[(0, 'test_1'), (1, 'test_2'), (2, 'test_3')]

[(10, 'test_1'), (11, 'test_2'), (12, 'test_3')]

Come menzionato nei commenti, questo approccio con range non funzionerà con iterabili arbitrari come fa la enumeratefunzione originale .


La ragione per cui menziona l'altra risposta itertoolsè che il tuo rangeapproccio funziona solo con i contenitori. enumeratefunziona con iterabili arbitrari; se vuoi iterare un file, for lineno, line in enumerate(myfile):funziona, ma non puoi farlo range(len(myfile))perché la lunghezza non è nota fino a quando non raggiungi EOF.
ShadowRanger,

12

La funzione di enumerazione funziona come segue:

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)

L'output è

(0, 'I like movie')
(1, " But I don't like the cast")
(2, ' The story is very nice')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.