enumerate () - création d'un générateur en Python


88

J'aimerais savoir ce qui se passe lorsque je passe le résultat d'une fonction de générateur à enumerate () de python. Exemple:

def veryBigHello():
    i = 0
    while i < 10000000:
        i += 1
        yield "hello"

numbered = enumerate(veryBigHello())
for i, word in numbered:
    print i, word

L'énumération est-elle répétée paresseusement, ou est-ce qu'elle insère tout dans la première? Je suis sûr à 99,999% que c'est paresseux, puis-je le traiter exactement de la même manière que la fonction générateur, ou dois-je faire attention à quoi que ce soit?


1
Je suppose que vous voulez incrémenter i dans veryBigHello.
— robert

@robert: si je ne me trompe pas, je augmente automatiquement
— the_drow

@the_drow Pas dans la veryBigHellofonction elle-même.
— Will McCutchen

1
@Will: Oh, c'est exact. Mais ce n'est que pinailler. C'est un exemple. Corrigé de toute façon.
— the_drow

Réponses:


103

C'est paresseux. C'est assez facile de prouver que c'est le cas:

>>> def abc():
...     letters = ['a','b','c']
...     for letter in letters:
...         print letter
...         yield letter
...
>>> numbered = enumerate(abc())
>>> for i, word in numbered:
...     print i, word
...
a
0 a
b
1 b
c
2 c

Est-ce Python 2 ou 3 (ou les deux)? Est-ce paresseux dans les deux? Je l' ai testé sur Python 2 et il est paresseux.
— becko le

2
J'ai testé cela sur Python 3.5.2, et il évalue paresseusement.
— gobernador

42

C'est encore plus facile à dire que l'une ou l'autre des suggestions précédentes:

$ python
Python 2.5.5 (r255:77872, Mar 15 2010, 00:43:13)
[GCC 4.3.4 20090804 (release) 1] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> abc = (letter for letter in 'abc')
>>> abc
<generator object at 0x7ff29d8c>
>>> numbered = enumerate(abc)
>>> numbered
<enumerate object at 0x7ff29e2c>

Si enumerate n'effectuait pas d'évaluation différée, il renverrait [(0,'a'), (1,'b'), (2,'c')]ou un équivalent (presque).

Bien sûr, enumerate n'est en réalité qu'un générateur sophistiqué:

def myenumerate(iterable):
   count = 0
   for _ in iterable:
      yield (count, _)
      count += 1

for i, val in myenumerate((letter for letter in 'abc')):
    print i, val

2
Merci pour cette explication. J'ai eu un peu de mal à trouver la réponse acceptée. Au moins jusqu'à ce que je voie le vôtre.
— Trendsetter37

13

Puisque vous pouvez appeler cette fonction sans sortir des exceptions de mémoire, c'est définitivement paresseux

def veryBigHello():
    i = 0
    while i < 1000000000000000000000000000:
        yield "hello"

numbered = enumerate(veryBigHello())
for i, word in numbered:
    print i, word

0

Alternative à la vieille école puisque j'utilisais un générateur écrit par quelqu'un d'autre (sklearn) qui ne fonctionnait pas avec les approches ici.

i=(-1)
for x in some_generator:
    i+=1
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.