Que signifie enumerate ()?

Réponses:

513

La enumerate()fonction ajoute un compteur à un itérable.

Ainsi, pour chaque élément de cursor, un tuple est produit avec (counter, element); la forboucle lie cela à row_numberet row, respectivement.

Démo:

>>> 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

Par défaut, enumerate()commence à compter 0mais si vous lui donnez un deuxième argument entier, il commencera à partir de ce nombre à la place:

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

Si vous deviez réimplémenter enumerate()en Python, voici deux façons d'y parvenir; l'un utilisant itertools.count()pour effectuer le comptage, l'autre comptant manuellement dans une fonction générateur :

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)

et

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

L' implémentation réelle en C est plus proche de ce dernier, avec des optimisations pour réutiliser un seul objet tuple pour le for i, ...cas de déballage commun et en utilisant une valeur entière C standard pour le compteur jusqu'à ce que le compteur devienne trop grand pour éviter d'utiliser un objet entier Python (qui est sans bornes).

Martijn Pieters
la source
92

C'est une fonction intégrée qui renvoie un objet qui peut être itéré. Consultez la documentation .

En bref, il boucle sur les éléments d'un itérable (comme une liste), ainsi que d'un numéro d'index, combinés dans un tuple:

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

impressions

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

C'est utile si vous voulez faire une boucle sur une séquence (ou autre chose itérable), et que vous voulez également avoir un compteur d'index disponible. Si vous voulez que le compteur démarre à partir d'une autre valeur (généralement 1), vous pouvez donner cela comme deuxième argument à enumerate.

RemcoGerlich
la source
1
si vous ajoutez une deuxième variable à itemalors vous pouvez supprimer la parenthèse: D
Abdelouahab
2
Pedantic: C'est une fonction renvoyant un itérateur, pas un générateur. Les générateurs sont une classe spécifique de fonctions définies par l' utilisateur (en utilisant yield/ yield from, ou des expressions de générateur, qui implicitement yield); enumeraten'est pas un générateur. Pour toutes les fins liées à la saisie de canard, il n'y a pas de différence, mais la vérification de type explicite et les documents en langage Python n'utilisent le terme "générateur" que pour un seul but, qui ne couvre pas enumerate.
ShadowRanger
22

Je lis un livre ( Effective Python ) de Brett Slatkin et il montre une autre façon de parcourir une liste et de connaître également l'index de l'élément actuel dans la liste, mais il suggère qu'il vaut mieux ne pas l'utiliser et l'utiliser à la enumerateplace. Je sais que vous avez demandé ce que signifie énumérer, mais quand j'ai compris ce qui suit, j'ai également compris comment enumeratefaciliter l'itération sur une liste tout en connaissant l'index de l'élément actuel (et plus lisible).

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

La sortie est:

0 a
1 b
2 c

J'ai aussi l'habitude de faire quelque chose, encore plus idiot avant de lire sur la enumeratefonction.

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

Il produit la même sortie.

Mais avec enumerateje dois juste écrire:

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

Comme d'autres utilisateurs l'ont mentionné, enumerateest un générateur qui ajoute un index incrémentiel à côté de chaque élément d'un itérable.

Donc , si vous avez un mot à dire la liste l = ["test_1", "test_2", "test_3"], la list(enumerate(l))vous donnera quelque chose comme ceci: [(0, 'test_1'), (1, 'test_2'), (2, 'test_3')].

Maintenant, quand c'est utile? Un cas d'utilisation possible consiste à parcourir les éléments et à ignorer un élément spécifique dont vous ne connaissez que l'index dans la liste mais pas sa valeur (car sa valeur n'est pas connue à ce moment-là).

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

   # Do something with the other `value`

Ainsi, votre code se lit mieux car vous pouvez également faire une boucle for régulière avec rangemais pour accéder aux éléments dont vous avez besoin pour les indexer (c'est-à-dire joint_values[i]).

Bien qu'un autre utilisateur ait mentionné une implémentation de l' enumerateutilisation zip, je pense qu'une manière plus pure (mais légèrement plus complexe) sans utiliser itertoolsest la suivante:

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

Exemple:

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

Production:

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

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

Comme mentionné dans les commentaires, cette approche avec plage ne fonctionnera pas avec des itérables arbitraires comme le enumeratefait la fonction d' origine .

Rafael
la source
La raison pour laquelle l'autre réponse mentionne itertoolsest que votre rangeapproche ne fonctionne qu'avec des conteneurs. enumeratefonctionne avec des itérables arbitraires; si vous voulez itérer un fichier, for lineno, line in enumerate(myfile):ça marche, mais vous ne pouvez pas le faire range(len(myfile))car la longueur n'est pas connue jusqu'à ce que vous atteigniez EOF.
ShadowRanger
12

La fonction énumération fonctionne comme suit:

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 sortie est

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