如何从一个发电机(在Python中)只select一个项目?
我有一个生成器函数,如下所示:
def myfunct(): ... yield result
调用这个函数的通常方法是:
for r in myfunct(): dostuff(r)
我的问题是,有没有办法从发生器中只要一个元素,只要我喜欢? 例如,我想要做一些事情:
while True: ... if something: my_element = pick_just_one_element(myfunct()) dostuff(my_element) ...
使用创build一个生成器
g = myfunct()
每次你想要一个项目,使用
g.next()
要么
next(g)
如果发生器退出,则会StopIteration
。 你可以根据需要捕获这个exception,或者使用next()
的default
参数:
next(g, default_value)
对于只select一个生成器的一个元素,在for
语句或list(itertools.islice(gen, 1))
使用break
list(itertools.islice(gen, 1))
根据你的例子(litterally),你可以这样做:
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()
,并且input结束处理不需要(隐蔽的) StopIteration
exception处理或额外的默认值比较。
如果你想在发生器结束的时候做一些特殊的事情,那么只需要for
语句部分的else:
next()
/ .next()
注意事项:
在Python3中, .next()
方法被重新命名为.__next__()
,理由很充分:它被认为是低级的(PEP 3114)。 在Python 2.6之前,内build函数next()
不存在。 而且甚至有人讨论过将next()
移到operator
模块(这将是明智的),因为它的内部名字很less需要和可疑的通货膨胀。
next()
没有默认的情况下使用next()
仍然是非常低级的练习 – 在正常的应用程序代码中,像隐藏的螺栓一样抛出神秘的StopIteration
。 并且使用next()
和默认的sentinel(最好应该是直接在builtins
的next()
的唯一选项next()
是有限的,并且经常给出奇怪的非pythonic逻辑/可读性的理由。
底线:使用next()应该非常less见 – 就像使用operator
module的函数一样。 for x in iterator
使用for x in iterator
, islice
, list(iterator)
和其他无缝接受迭代器的函数是在应用程序级别上使用迭代器的自然方式 – 而且总是可能的。 next()
是低级的,一个额外的概念,不明显 – 正如这个线程的问题所示。 而例如使用break
是常规的。
我不相信有一个方便的方法来从发生器中检索任意值。 生成器将提供一个next()方法来遍历自己,但是不会立即产生完整的序列来节省内存。 这是一个生成器和一个列表之间的function差异。
generator = myfunct() while True: my_element = generator.next()
确保捕捉到最后一个元素被引发后引发的exception
我相信唯一的办法是从迭代器中获取列表,然后从列表中获取所需的元素。
l = list(myfunct()) l[4]