Que fait for row_number, row in enumerate(cursor):
en Python?
Que signifie enumerate
dans ce contexte?
La enumerate()
fonction ajoute un compteur à un itérable.
Donc, pour chaque élément de cursor
, un tuple est produit avec (counter, element)
; la boucle for
lie cela à row_number
et 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 à 0
, mais si vous lui donnez un deuxième argument entier, il commencera à partir de ce nombre:
>>> 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 manières de le réaliser. une en utilisant itertools.count()
pour faire le comptage, l'autre en comptant manuellement dans un fonction de 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
Le implémentation réelle en C est plus proche de ce dernier, avec des optimisations permettant de réutiliser un seul objet Tuple pour le cas commun for i, ...
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 (non limité).
C'est une fonction génératrice intégrée, voir http://docs.python.org/2/library/functions.html#enumerate .
En bref, il donne les éléments d'un itérateur, ainsi qu'un numéro d'index:
for item in enumerate(["a", "b", "c"]):
print item
empreintes
(0, "a")
(1, "b")
(2, "c")
Il est utile si vous souhaitez effectuer une boucle sur un interator et souhaitez également disposer d'un compteur d'index. Si vous voulez que le compteur commence à partir d'une autre valeur (généralement 1), vous pouvez le définir comme second argument de enumerate
.
Je lis un livre ('Effective Python') de Brett Slatkin et il montre un autre moyen de parcourir une liste et de connaître l'index de l'élément en cours dans la liste. MAIS suggère de ne pas l'utiliser et d'utiliser plutôt enumerate
. Je sais que vous avez demandé ce que signifie énumérer, mais quand j’ai compris ce qui suit, j’ai aussi compris comment enumerate
rend plus facile la itération sur une liste tout en connaissant l’index de l’item courant (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'avais aussi l'habitude de faire quelque chose, encore plus bête avant de lire sur la fonction enumerate
.
i = 0
for n in list_of_letters:
print (i, n)
i = i +1
Il produit le même résultat.
Mais avec enumerate
il ne me reste plus qu'à écrire:
list_of_letters = ['a', 'b', 'c']
for i, letter in enumerate(list_of_letters):
print (i, letter)
Comme d'autres utilisateurs l'ont mentionné, enumerate
est un générateur qui ajoute un index incrémentiel à côté de chaque élément d'un élément itérable.
Donc, si vous avez une liste avec 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 cela est utile? Un cas d'utilisation possible consiste à itérer sur des éléments et à ignorer un élément spécifique dont vous ne connaissez que son index dans la liste, mais pas sa valeur (car sa valeur n'est pas connue à l'époque).
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 créer une boucle for régulière avec range
, mais pour accéder aux éléments, vous devez les indexer (c'est-à-dire joint_values[i]
).
Bien qu'un autre utilisateur ait mentionné une implémentation de enumerate
en utilisant Zip
, je pense qu'une méthode plus pure (mais légèrement plus complexe) sans utiliser itertools
est 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)
Sortie:
[(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 range ne fonctionnera pas avec des itérables arbitraires, contrairement à la fonction originale enumerate
.
La fonction énumérer 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')