Chciałbym wiedzieć, co się stanie, gdy przekażę wynik funkcji generatora do metody enumerate () w języku Python. Przykład:
def veryBigHello():
i = 0
while i < 10000000:
i += 1
yield "hello"
numbered = enumerate(veryBigHello())
for i, word in numbered:
print i, word
Czy wyliczenie powtarza się leniwie, czy też siorbi wszystko w pierwszym? Jestem na 99,999% pewien, że jest leniwy, więc czy mogę traktować go dokładnie tak samo, jak funkcję generatora, czy też muszę na coś uważać?
veryBigHello
samej funkcji.Odpowiedzi:
To jest leniwe. Dość łatwo udowodnić, że tak jest:
>>> 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
źródło
To jeszcze łatwiejsze do stwierdzenia niż którakolwiek z poprzednich sugestii:
$ 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 przeprowadzi leniwej oceny, zwróci
[(0,'a'), (1,'b'), (2,'c')]
lub jakiś (prawie) odpowiednik.Oczywiście enumerate to naprawdę fantazyjny 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
źródło
Ponieważ można wywołać tę funkcję bez wychodzenia z pamięci, jest ona zdecydowanie leniwa
def veryBigHello(): i = 0 while i < 1000000000000000000000000000: yield "hello" numbered = enumerate(veryBigHello()) for i, word in numbered: print i, word
źródło
Oldschoolowa alternatywa, ponieważ korzystałem z generatora, który ktoś inny (sklearn) napisał, a który nie działał z opisanymi tu podejściami.
i=(-1) for x in some_generator: i+=1
źródło