2010-08-03 35 views
49

Je voudrais savoir ce qui se passe quand je passe le résultat d'une fonction de générateur à enumerate() de python. Exemple:enumerate() - un générateur en Python

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 itérativement par la suite, ou est-ce que tout est glissé dans le premier? Je suis sûr à 99,999% que c'est paresseux, alors est-ce que je peux le traiter exactement comme la fonction du générateur, ou dois-je faire attention à quoi que ce soit?

+0

Je suppose que vous voulez dire à incrémenter i dans veryBigHello. – robert

+0

@robert: si je ne me trompe pas i est automatiquement augmenté –

+0

@the_drow Pas dans la fonction 'veryBigHello' elle-même. –

Répondre

61

C'est paresseux. Il est assez facile de prouver que 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 
+0

Est-ce Python 2 ou 3 (ou les deux)? Est-il paresseux dans les deux? J'ai testé sur Python 2 et c'est * paresseux. – becko

10

Comme vous pouvez appeler cette fonction sans sortir des exceptions de mémoire, il est definitly paresseux

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

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

Il est encore plus facile de dire que l'une des précédente suggèrent :

$ 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 Énumérer n'a pas effectué l'évaluation paresseuse qu'il retournerait [(0,'a'), (1,'b'), (2,'c')] ou un équivalent (presque).

Bien sûr, énumérer est vraiment juste 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 
+2

Merci pour cette explication. J'ai eu un peu de mal à trouver la réponse acceptée. Au moins jusqu'à ce que j'ai vu le tien. – trendsetter37

+1

Ceci devrait être la réponse acceptée – cowbert