【发布时间】:2016-05-29 21:44:36
【问题描述】:
给定一个 Python 协程:
def coroutine():
score = 0
for _ in range(3):
score = yield score + 1
我想像这样在一个简单的循环中使用它:
cs = coroutine()
for c in cs:
print(c)
cs.send(c + 1)
...我希望打印出来
1
3
5
但实际上,我在yield score + 1 线上遇到了一个异常:
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
如果我手动调用next,我可以让它工作:
c = next(cs)
while True:
print(c)
try:
c = cs.send(c + 1)
except StopIteration:
break
但我不喜欢我需要使用 try/except,因为生成器通常非常优雅。
那么,有没有办法在不显式处理StopIteration 的情况下使用这样的有限协程?我很高兴同时更改生成器和迭代它的方式。
第二次尝试
Martijn 指出for 循环和我对send 的调用都推进了迭代器。很公平。那么,为什么我不能在协程循环中使用两个 yield 语句来解决这个问题?
def coroutine():
score = 0
for _ in range(3):
yield score
score = yield score + 1
cs = coroutine()
for c in cs:
print(c)
cs.send(c + 1)
如果我尝试这样做,我会得到同样的错误,但在 send 行。
0
None
Traceback (most recent call last):
File "../coroutine_test.py", line 10, in <module>
cs.send(c + 1)
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
【问题讨论】:
-
for-循环协程并没有什么意义。与协程交互的方式与与普通生成器的正常交互方式完全不同。 -
yield score + 1返回None并将其分配给score,因此下一次迭代尝试将 1 添加到None。
标签: python generator coroutine