enumerate () - создание генератора в Python


88

Я хотел бы знать, что происходит, когда я передаю результат функции генератора в enumerate () python. Пример:

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

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

Перечисление повторяется лениво или все перебирает в первую? Я на 99,999% уверен, что он ленив, поэтому могу ли я относиться к нему точно так же, как к функции генератора, или мне нужно что-то остерегаться?


1
Я предполагаю, что вы хотите увеличить i в veryBigHello.
Роберт

@robert: если я не ошибаюсь, i автоматически увеличивается
the_drow

@the_drow Не в самой veryBigHelloфункции.
Уилл МакКатчен,

1
@Will: О, правильно. Но это просто придирки. Это пример. Все равно исправлено.
the_drow

Ответы:


103

Это лениво. Доказать, что это так, довольно легко:

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

Это Python 2 или 3 (или оба)? Лень в обоих? Я тестировал на Python 2 и это лень.
becko

2
Я тестировал это на Python 3.5.2, и он лениво оценивает.
gobernador

42

Это даже легче сказать, чем предполагалось ранее:

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

Если enumerate не выполнял ленивую оценку, он вернул бы [(0,'a'), (1,'b'), (2,'c')]или какой-то (почти) эквивалент.

Конечно, enumerate - это просто причудливый генератор:

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
Спасибо за это объяснение. Мне было немного трудно понять принятый ответ. По крайней мере, пока я не увидел твою.
trendsetter37

13

Поскольку вы можете вызвать эту функцию, не выходя из исключений памяти, она определенно ленива

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

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

0

Альтернатива старой школы, поскольку я использовал генератор, который написал кто-то другой (sklearn), который не работал с подходами здесь.

i=(-1)
for x in some_generator:
    i+=1
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.