我正在使用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
答案 0 :(得分:3)
在Python中,如果函数中存在yield
,则Python会将其视为生成器。在生成器中,任何返回都将使用返回值引发StopIteration
。这是Python 3.3中的一项新功能:请参阅PEP 380和here。 check_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中的一项新功能。