我有一个像下面这样的生成器函数:
def myfunct():
...
yield result
通常调用这个函数的方法是:
for r in myfunct():
dostuff(r)
我的问题是,有没有一种方法可以随时从生成器中获得一个元素?
例如,我想做这样的事情:
while True:
...
if something:
my_element = pick_just_one_element(myfunct())
dostuff(my_element)
...
如果只选择生成器中的一个元素,请在For语句中使用break,或者在list(itertools. list)中使用break。islice(创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异常处理或额外的默认值比较。
for语句部分的else:仅当您想在生成器结束的情况下做一些特殊的事情时才需要。
注意next() / .next():
在Python3中,.next()方法被重命名为.__next__()有很好的理由:它被认为是低级的(PEP 3114)。在Python 2.6之前,内置函数next()并不存在。甚至还讨论了将next()转移到操作符模块(这本来是明智的),因为它很少需要内置名称,而且有问题。
在没有默认值的情况下使用next()仍然是非常低级的实践——在正常的应用程序代码中公开抛出神秘的StopIteration,就像晴天霹雳一样。并且使用默认哨兵(最好是在内置程序中直接使用next()的唯一选项)使用next()是有限的,并且经常导致奇怪的非python逻辑/可读性。
底线:应该很少使用next()——就像使用operator模块的函数一样。在iterator、islice、list(iterator)和其他无缝接受迭代器的函数中使用for x是在应用程序级使用迭代器的自然方式——而且总是可能的。Next()是低级别的,一个额外的概念,不明显-正如这个线程的问题所显示的那样。而使用break in for则是传统用法。