2010-08-03 11 views
49

Chciałbym wiedzieć, co się stanie, gdy przekazuję wynik funkcji generatora do wyliczenia Pythona(). Przykład:wyliczanie() - generowanie w Pythonie

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

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

Czy wyliczenie iterowało leniwie, czy też wszystko wbiło w pierwszy? Mam 99,999% pewności, że jest leniwy, więc czy mogę traktować to dokładnie tak samo, jak funkcję generatora, czy też muszę uważać na wszystko?

+0

Przypuszczam, to znaczy, aby zwiększyć I w veryBigHello. – robert

+0

@robert: jeśli się nie mylę, zostanie automatycznie zwiększony –

+0

@the_drow Nie w samej funkcji 'veryBigHello'. –

Odpowiedz

61

Jest leniwy. Jest to dość łatwe do udowodnienia, że ​​to przypadek:

>>> 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

Czy jest to Python 2 lub 3 (lub oba)? Czy jest leniwy w obu? Testowałem na Pythonie 2 i * jest * leniwy. – becko

10

Ponieważ można wywołać tę funkcję bez wychodzenia z wyjątkami pamięci to zdecydowanie jest leniwy

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

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

To jeszcze łatwiej powiedzieć niż którakolwiek z poprzednich sugerować :

$ 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> 

Jeśli enumerate nie dokonywała oceny leniwy byłoby powrócić [(0,'a'), (1,'b'), (2,'c')] lub niektóre (prawie) równoważne.

Oczywiście wyliczyć to naprawdę tylko wyobraźnia generator:

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

Dzięki za wyjaśnienie. Trochę mi było ciężko znaleźć odpowiedź. Przynajmniej dopóki nie zobaczyłem twojego. – trendsetter37

+1

To powinna być zaakceptowana odpowiedź – cowbert