如何从生成器中只选择一项(在 python 中)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4741243/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 17:17:54  来源:igfitidea点击:

how to pick just one item from a generator (in python)?

pythoniteratorgeneratorpython-2.x

提问by Alexandros

I have a generator function like the following:

我有一个如下的生成器函数:

def myfunct():
  ...
  yield result

The usual way to call this function would be:

调用此函数的通常方法是:

for r in myfunct():
  dostuff(r)

My question, is there a way to get just one element from the generator whenever I like? For example, I'd like to do something like:

我的问题是,有没有办法在我喜欢的时候只从生成器中获取一个元素?例如,我想做这样的事情:

while True:
  ...
  if something:
      my_element = pick_just_one_element(myfunct())
      dostuff(my_element)
  ...

采纳答案by Sven Marnach

Create a generator using

使用创建生成器

g = myfunct()

Everytime you would like an item, use

每次你想要一个项目时,使用

next(g)

(or g.next()in Python 2.5 or below).

(或g.next()在 Python 2.5 或更低版本中)。

If the generator exits, it will raise StopIteration. You can either catch this exception if necessary, or use the defaultargument to next():

如果生成器退出,它将引发StopIteration。如有必要,您可以捕获此异常,或使用以下default参数next()

next(g, default_value)

回答by keegan3d

I believe the only way is to get a list from the iterator then get the element you want from that list.

我相信唯一的方法是从迭代器中获取一个列表,然后从该列表中获取您想要的元素。

l = list(myfunct())
l[4]

回答by g.d.d.c

I don't believe there's a convenient way to retrieve an arbitrary value from a generator. The generator will provide a next() method to traverse itself, but the full sequence is not produced immediately to save memory. That's the functional difference between a generator and a list.

我不相信有一种方便的方法可以从生成器中检索任意值。生成器将提供 next() 方法来遍历自身,但不会立即生成完整序列以节省内存。这就是生成器和列表之间的功能差异。

回答by John

generator = myfunct()
while True:
   my_element = generator.next()

make sure to catch the exception thrown after the last element is taken

确保捕获最后一个元素被获取后抛出的异常

回答by kxr

For picking just one element of a generator use breakin a forstatement, or list(itertools.islice(gen, 1))

用于breakfor语句中仅选择生成器的一个元素,或list(itertools.islice(gen, 1))

According to your example (literally) you can do something like:

根据您的示例(字面意思),您可以执行以下操作:

while True:
  ...
  if something:
      for my_element in myfunct():
          dostuff(my_element)
          break
      else:
          do_generator_empty()

If you want "get just one element from the[once generated] generator whenever I like" (I suppose 50% thats the original intention, and the most common intention) then:

如果你想“只要我喜欢就从[一次性生成]生成器中获取一个元素”(我想 50% 是最初的意图,也是最常见的意图),那么:

gen = myfunct()
while True:
  ...
  if something:
      for my_element in gen:
          dostuff(my_element)
          break
      else:
          do_generator_empty()

This way explicit use of generator.next()can be avoided, and end-of-input handling doesn't require (cryptic) StopIterationexception handling or extra default value comparisons.

这种方式generator.next()可以避免显式使用,并且输入结束处理不需要(神秘的)StopIteration异常处理或额外的默认值比较。

The else:of forstatement section is only needed if you want do something special in case of end-of-generator.

else:for,如果你想要做一些特别的结束产生的case语句段时,才需要。

Note on next()/ .next():

注意next()/ .next()

In Python3 the .next()method was renamed to .__next__()for good reason: its considered low-level (PEP 3114). Before Python 2.6 the builtin function next()did not exist. And it was even discussed to move next()to the operatormodule (which would have been wise), because of its rare need and questionable inflation of builtin names.

在 Python3 中,该.next()方法被重命名.__next__()为有充分理由:它被认为是低级的(PEP 3114)。在 Python 2.6 之前,内置函数next()不存在。甚至还讨论了转移next()operator模块(这本来是明智的),因为它很少需要和内置名称的可疑膨胀。

Using next()without default is still very low-level practice - throwing the cryptic StopIterationlike a bolt out of the blue in normal application code openly. And using next()with default sentinel - which best should be the only option for a next()directly in builtins- is limited and often gives reason to odd non-pythonic logic/readablity.

next()没有默认值的情况下使用仍然是非常低级的实践 -StopIteration在正常的应用程序代码中公开地像突然出现的螺栓一样抛出神秘的东西。并使用next()默认哨兵 - 最好应该是next()直接输入的唯一选择builtins- 是有限的,并且经常为奇怪的非pythonic逻辑/可读性提供理由。

Bottom line: Using next() should be very rare - like using functions of operatormodule. Using for x in iterator, islice, list(iterator)and other functions accepting an iterator seamlessly is the natural way of using iterators on application level - and quite always possible. next()is low-level, an extra concept, unobvious - as the question of this thread shows. While e.g. using breakin foris conventional.

底线:使用 next() 应该很少见——就像使用operator模块的函数一样。使用for x in iteratorislicelist(iterator)等功能接受一个迭代器无缝地使用是在应用层上的迭代器的自然方式-而且相当总是可能的。next()是低级的,一个额外的概念,不明显 - 正如该线程的问题所示。而例如使用breakinfor是常规的。

回答by andrii

Generator is a function that produces an iterator. Therefore, once you have iterator instance, use next()to fetch the next item from the iterator. As an example, use next() function to fetch the first item, and later use for into process remaining items:

Generator 是一个产生迭代器的函数。因此,一旦有了迭代器实例,就可以使用next()从迭代器中获取下一项。例如,使用 next() 函数获取第一项,然后for in用于处理剩余项:

# create new instance of iterator by calling a generator function
items = generator_function()

# fetch and print first item
first = next(items)
print('first item:', first)

# process remaining items:
for item in items:
    print('next item:', item)

回答by Dave Rove

For those of you scanning through these answers for a complete working example for Python3... well here ya go:

对于那些浏览这些答案以获取 Python3 的完整工作示例的人......好吧,你去吧:

def numgen():
    x = 1000
    while True:
        x += 1
        yield x

nums = numgen() # because it must be the _same_ generator

for n in range(3):
    numnext = next(nums)
    print(numnext)

This outputs:

这输出:

1001
1002
1003