Як пройти через генератор


81

Як можна пройти цикл через генератор? Я думав про це так:

gen = function_that_returns_a_generator(param1, param2)
if gen: # in case the generator is null
    while True:
        try:
            print gen.next()
        except StopIteration:
            break

Чи є більш пітонічний спосіб?


Я б запропонував використовувати break; ніcontinue
Джон Клементс

Я б насправді зробив це таким чином у випадку, коли генератор може накинути виняток на елемент, але ви не хочете зупиняти ітерацію.
грабіж

Відповіді:


145

Просто

for x in gen:
    # whatever

зробить трюк. Зверніть увагу, що if genзавжди повертається True.


6
Ні, if genне завжди повертається True. Якщо операція function_that_returns_a_generator()повертається None, genобчислюється до Falseу ifзаяві.
drevicko

44
@drevicko: Я припускав, що function_that_returns_a_generator()повертає генератор ( жирне припущення, чи не так?). Noneне є генератором.
Sven Marnach

Оскільки OP просить "пітонічний шлях", ця відповідь видається цілком правомірною, враховуючи те, що Python виступає за EAFP ;-)
DerMike

17
for item in function_that_returns_a_generator(param1, param2):
    print item

Вам не потрібно турбуватися про тест, щоб перевірити, чи повертається що-небудь вашою функцією, ніби нічого не повернуто, ви не ввійдете в цикл.


9

Якщо вам не потрібен вихід генератора, оскільки ви дбаєте лише про його побічні ефекти, ви можете скористатися наступним одноклассником:

for _ in gen: pass

3
або простоlist(gen)
aiven

7

Ви можете просто прокрутити його:

>>> gen = (i for i in range(1, 4))
>>> for i in gen: print i
1
2
3

Але майте на увазі, що ви можете повторити лише один раз. Наступного разу генератор буде порожнім:

>>> for i in gen: print i
>>> 

4

Просто обробляйте це як будь-який інший ітератор:

for val in function_that_returns_a_generator(p1, p2):
    print val

Зауважте, що if gen:завжди буде True, тож це помилковий тест


2

Якщо ви хочете вручну рухатись через генератор (тобто працювати з кожним циклом вручну), ви можете зробити щось подібне:

    from pdb import set_trace

    for x in gen:
        set_trace()
        #do whatever you want with x at the command prompt
        #use pdb commands to step through each loop of the generator e.g., >>c #continue   

1
від pdb import set_trace # no () :)
Влад К.

1

Інші відповіді підходять для складних сценаріїв. Якщо ви просто хочете передати елементи в список:

x = list(generator)

(або, якщо ви просто хочете запустити генератор робити щось, просто list(generator).

Для простої попередньої обробки використовуйте розуміння списку:

x = [tup[0] for tup in generator]

Або коли ви хочете виконувати прості функції:

# didn't assign to variable b/c we don't care about what the print() function returns
[print(x) for x in gen]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.