要从生成器中选择一个元素,请在 for
语句中使用 break
,或者使用 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
异常处理或额外的默认值比较。
for
语句部分中的 else:
只在想要在生成器结束时执行特殊操作时才需要。
next()
/ .next()
注意事项:
在 Python3 中,.next()
方法被重命名为 .__next__()
,这是有充分理由的(PEP 3114)。在 Python 2.6 之前,内置函数 next()
并不存在。甚至曾经有讨论将 next()
移动到 operator
模块中(这是明智的),因为它很少使用并且增加内置名称的问题值得商榷。
在没有默认值的情况下使用 next()
仍然是非常低级的做法 - 在正常应用程序代码中突然抛出晦涩难懂的 StopIteration
异常。而使用带有默认位置标记的 next()
- 最好是直接在 builtins
中唯一的选项 - 是有限制的并且常常导致奇怪的非Pythonic逻辑/可读性。
底线:使用 next()
应该非常罕见 - 就像使用 operator
模块的函数一样。在应用程序级别上,使用 for x in iterator
、islice
、list(iterator)
和其他接受迭代器的函数是使用迭代器的自然方式,并且几乎总是可行的。 next()
是低级的,额外的概念,不明显的 - 就像这个主题的问题一样。而在 for
中使用 break
则是常规做法。
next(gen, default)
可以用于避免StopIteration
异常。例如,对于一个生成字符串的生成器,使用next(g, None)
将在迭代完成后产生一个字符串或者None。 - Attilanext(g)
。这将内部调用g.__next__()
,但你不必担心这个,就像你通常不关心len(a)
内部调用a.__len__()
一样。 - Sven Marnachg.next()
等同于g.__next__()
。自Python 2.6起,就有了内置函数next(iterator)
,在所有新的Python代码中都应使用它,如果需要支持Python版本小于等于2.5,则可以轻松地回溯实现。 - Jonathan Baldwin