Histoire de la question
La fonction enumerate() est apparue en Python pour permettre une itération conviviale et idiomatique sur les éléments d'une séquence tout en obtenant l'indice actuel. Cela est particulièrement important, car auparavant, il était souvent recommandé de gérer manuellement un compteur séparé, ce qui était considéré comme non idiomatique et moins lisible.
Problème
Dans les boucles, il est souvent nécessaire de connaître non seulement la valeur actuelle, mais aussi son indice dans la séquence. La gestion manuelle des indices avec une variable séparée (i) et l'appel de range(len(seq)) mène à des erreurs (écart entre indices et valeurs, duplication de code) et diminue la lisibilité.
Solution
enumerate() renvoie un itérateur paresseux qui, à chaque étape, renvoie un tuple (indice, valeur) de l'élément actuel. Avec elle, il est possible de travailler avec les indices de manière élégante et fiable :
colors = ['red', 'green', 'blue'] for idx, color in enumerate(colors): print(idx, color)
L'itération commence à zéro, mais il est possible d'indiquer n'importe quelle valeur de départ :
for idx, color in enumerate(colors, start=1): print(idx, color)
Caractéristiques clés :
enumerate() fonctionne avec n'importe quelle séquence itérable, renvoie un tuple (indice, élément)start, ce qui peut être pratiquePeut-on désactiver le retour de l'indice et ne garder que les valeurs en utilisant enumerate() ?
Non, enumerate() renvoie toujours des paires (indice, valeur). Si seule la valeur est requise, utilisez une boucle for classique :
for value in my_list: print(value)
Peut-on utiliser enumerate() avec des objets non indexables, comme des générateurs ?
Oui, enumerate() fonctionne avec tout objet itérable, y compris les générateurs. L'indexation se fera selon l'ordre d'apparition des valeurs :
def mygen() : for i in range(3) : yield chr(ord('a')+i) for idx, val in enumerate(mygen()) : print(idx, val) # 0 a, 1 b, 2 c
Peut-on définir automatiquement un indice de départ différent de 0, et que se passe-t-il avec des valeurs négatives ?
Oui, enumerate() a un argument start. Si vous passez une valeur négative, l'indexation commencera à partir de cette valeur :
for idx, x in enumerate(['a', 'b', 'c'], start=-3): print(idx, x) # -3 a, -2 b, -1 c
range(len(seq)) au lieu de enumerate() pour parcourir une liste — cela rend le code moins idiomatiqueDans l'équipe, ils maintiennent un grand code et utilisent souvent :
for i in range(len(mylist)): process(i, mylist[i])
Avantages :
Inconvénients :
Après une refactorisation, ils passent à :
for idx, val in enumerate(mylist): process(idx, val)
Avantages :
Inconvénients :