Je voudrais 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 que tout est glissé dans le premier? Je suis sûr à 99,999% qu'il est paresseux, alors 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?
C'est paresseux. Il 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
Il est encore plus facile à dire que l'un des précédents:
$ 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 paresseuse, il retournerait [(0,'a'), (1,'b'), (2,'c')]
ou un équivalent (presque).
Bien sûr, énumérer n'est vraiment qu'un générateur de fantaisie:
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
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