无法返回生成器实例。为什么?

时间:2016-08-12 15:43:05

标签: python python-3.x if-statement generator

我正在使用python 3.5。 当我尝试返回生成器函数实例时,我收到StopIteration错误。为什么呢?

这是我的代码:

>>> def gen(start, end):
... '''generator function similar to range function'''
...    while start <= end:
...       yield start
...       start += 1
...
>>> def check(ingen, flag=None):
...    if flag:
...        for n in ingen:
...            yield n*2
...    else:
...        return ingen
...
>>> # Trigger else clause in check function
>>> a = check(gen(1,3))
>>> next(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration: <generator object gen at 0x7f37dc46e828>

看起来,在else子句返回生成器之前,生成器已经用尽了。

使用此功能可以正常工作:

>>> def check_v2(ingen):
...     return ingen
...
>>> b = check_v2(gen(1, 3))
>>> next(b)
1
>>> next(b)
2
>>> next(b)
3

4 个答案:

答案 0 :(得分:3)

在Python中,如果函数中存在yield,则Python会将其视为生成器。在生成器中,任何返回都将使用返回值引发StopIteration。这是Python 3.3中的一项新功能:请参阅PEP 380herecheck_v2有效,因为它不包含yield,因此是正常函数。

有两种方法可以达到你想要的效果:

  • return更改为yield中的check
  • 让来电者陷阱StopIteration,如下所示

    try:
        next(a)
    except StopIteration as ex:
        print(ex.value)
    

答案 1 :(得分:2)

当生成器命中其return语句(显式或非显式)时,它会引发StopIteration。所以当你return ingen结束迭代时。

check_v2不是生成器,因为它不包含yield语句,这就是它的工作原理。

答案 2 :(得分:1)

正如其他人所说,如果你从发电机返回,这意味着发电机已经停止产生物品,无论你返回什么,都会提高StopIteration

这意味着check实际上返回一个空的迭代器。

如果要返回其他生成器的结果,可以使用yield from

def check(ingen, flag=None):
    if flag:
        for n in ingen:
            yield n*2
    else:
        yield from ingen

答案 3 :(得分:0)

请参阅PEP 380

  

在生成器中,语句

return value
     

在语义上等同于

raise StopIteration(value)
     

除了当前except无法捕获异常   返回的发电机内的条款。

这是Python 3.3中的一项新功能。