как выбрать только один элемент из генератора (в Python)?
у меня есть функция генератора следующим образом:
def myfunct():
...
yield result
обычный способ вызова этой функции будет:
for r in myfunct():
dostuff(r)
мой вопрос, есть ли способ получить только один элемент из генератора, когда мне нравится? Например, я хотел бы сделать что-то вроде:
while True:
...
if something:
my_element = pick_just_one_element(myfunct())
dostuff(my_element)
...
5 ответов:
создать генератор, с помощью
g = myfunct()
каждый раз, когда вы хотели бы товар, использовать
next(g)
(или
g.next()
в Python 2.5 или ниже).если генератор выйдет, он поднимет
StopIteration
. Вы можете либо поймать это исключение, если это необходимо, либо использовать доnext()
:next(g, default_value)
для выбора только одного элемента генератора используйте
break
наfor
заявление, илиlist(itertools.islice(gen, 1))
в соответствии с вашим примером (в буквальном смысле) вы можете сделать, как:
while True: ... if something: for my_element in myfunct(): dostuff(my_element) break else: do_generator_empty()
если вы хотите "получить только один элемент из [образующиеся] генератор, когда мне нравится" (я полагаю, что 50% это первоначальное намерение, и наиболее распространенное намерение) тогда:
gen = myfunct() while True: ... if something: for my_element in gen: dostuff(my_element) break else: do_generator_empty()
таким образом явное использование
generator.next()
можно избежать, и обработка конца ввода не требует (загадочный)StopIteration
обработка исключений или дополнительные сравнения значений по умолчанию.The
else:
наfor
раздел заявления необходим только если вы хотите сделать что-то особенное в случае конца генератора.Примечание
next()
/.next()
:в Python3 the
.next()
метод был переименован в.__next__()
по уважительной причине: его считают низкоуровневым (PEP 3114). Перед Python 2.6 встроенная функцияnext()
не существовало. И это даже обсуждалось, чтобы двигатьсяnext()
доoperator
модуль (что было бы разумно), из-за его редкой необходимости и сомнительной инфляции встроенных имен.используя
next()
без дефолта по-прежнему очень низкоуровневая практика-бросание загадочногоStopIteration
как гром среди ясного неба в нормальном коде приложения открыто. И используяnext()
С sentinel по умолчанию - который лучше всего должен быть единственным вариантом дляnext()
непосредственно вbuiltins
- ограничен и часто дает повод нечетные номера-обновления логики/readablity.итог: использование next () должно быть очень редким - как использование функций
operator
модуль. Используяfor x in iterator
,islice
,list(iterator)
и другие функции, легко принимающие итератор, - это естественный способ использования итераторов на уровне приложения-и вполне всегда возможно.next()
является низкоуровневым, дополнительным понятием, неочевидным-как показывает вопрос этой темы. В то время как, например, с помощьюbreak
наfor
- это обычный.
Я не верю, что есть удобный способ получить произвольное значение из генератора. Генератор предоставит метод next () для прохождения себя, но полная последовательность не создается сразу для сохранения памяти. Это функциональное различие между генератором и списком.