Comment accéder à l'index dans les boucles 'Foreach' en Python

Souvent, lorsque vous faites une boucle sur une collection d’éléments en Python, vous devez aussi avoir un nombre ordinal associé à chaque élément. Un tel nombre est généralement appelé index.

La façon pythonique d’accéder à l’index en faisant une boucle foreach est d’utiliser la fonction intégrée enumerate().

La fonction enumerate() ajoute un index à chaque élément d’une collection itérable. Vous pouvez ensuite utiliser la fonction intégrée list() pour récupérer une liste de tuples.

>>> names = ['Bob', 'Alice', 'John', 'Cindy']
>>> list(enumerate(names))
[(0, 'Bob'), (1, 'Alice'), (2, 'John'), (3, 'Cindy')]

Note, l’indexation Python commence à partir de 0.

Cependant, si vous voulez commencer l’indexation à partir de 1 (par exemple, lors de l’impression d’un rapport de données), il est trivial de passer un argument start supplémentaire à enumerate.

>>> names = ['Bob', 'Alice', 'John', 'Cindy']
>>> list(enumerate(names), start=1)
[(1, 'Bob'), (2, 'Alice'), (3, 'John'), (4, 'Cindy')]

L’approche ci-dessus est également utile si vous imprimez des données provenant de différentes sources de données mais que vous voulez avoir un index cohérent pour tous les éléments de données.

>>> data_source1 = ['Bob', 'Alice', 'John', 'Cindy']
>>> data_source2 = ['Sarah', 'Jeff', 'Emily', 'Adam']
>>> list(enumerate(data_source1, start=1))
[(1, 'Bob'), (2, 'Alice'), (3, 'John'), (4, 'Cindy')]
>>> list(enumerate(data_source2, start=len(data_source1) + 1))
[(5, 'Sarah'), (6, 'Jeff'), (7, 'Emily'), (8, 'Adam')]

Notez que vous n’avez pas besoin de convertir un objet Enumerate en liste. C’est un objet itérable en lui-même, donc vous pouvez l’itérer directement par dessus.

>>> names = ['Bob', 'Alice', 'John', 'Cindy']
>>> for idx, name in enumerate(names):
...   print(name)
...
Bob
Alice
John
Cindy

Il peut y avoir d’autres moyens de mettre la main sur l’index pendant l’itération sur une collection d’éléments, mais l’utilisation de enumerate() est considérée comme canonique et est préférée.

Une autre option serait d’utiliser une variable d’index séparée, de l’initialiser manuellement et d’utiliser l’incrémenter manuellement à chaque itération. Une telle approche, cependant, serait considérée comme une réinvention de la roue et serait mal vue.

Voici une citation de PEP 279 dans laquelle la fonction enumerate() a été introduite.

Ce PEP introduit une nouvelle fonction intégrée, enumerate(), pour simplifier un idiome de bouclage couramment utilisé. Elle fournit à toutes les collections itérables le même avantage que iteritems() offre aux dictionnaires – une notation d’index compacte, lisible et fiable.

Vous pouvez vous demander s’il y a des implications en termes de performance à utiliser enumerate dans votre code. Eh bien, vous êtes libre de faire toutes les mesures, mais gardez à l’esprit que enumerate est un moyen idiomatique d’accéder à l’index d’un itérable dans une boucle pour-chacune. Le code idiomatique est recommandé par les mainteneurs Python et ils feront tout pour le faire fonctionner efficacement.

Et pour ceux d’entre vous qui sont les plus curieux, voici une implémentation possible de la fonction enumerate() du PEP ci-dessus.

def enumerate(collection):
   'Generates an indexed series:  (0,coll[0]), (1,coll[1]) ...'
   i = 0
   it = iter(collection)
   while 1:
       yield (i, it.next())
       i += 1
comments powered by Disqus