enumerate () - створення генератора в Python


88

Я хотів би знати, що відбувається, коли я передаю результат функції генератора в python's enumerate (). Приклад:

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 у дужеBigHello.
Роберт

@robert: якщо я не помиляюся, я автоматично збільшується
the_drow

@the_drow Не у самій veryBigHelloфункції.
Will McCutchen

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 і це лінь.
маня

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>

Якби перерахування не виконувало ліниве оцінювання, воно повернеться [(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.