考虑一下这个简单的协同线
In [9]: async def coro():
...: print('hello world')
...:
我们知道本机协同器不是迭代器。
In [12]: type(c)
Out[12]: coroutine
In [13]: next(c)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-13-e846efec376d> in <module>()
----> 1 next(c)
TypeError: 'coroutine' object is not an iterator
但是,如果运行协同线,则会得到一个StopIteration
错误。
In [10]: c = coro()
In [11]: c.send(None)
hello world
---------------------------
StopIteration Traceback (most recent call last)
<ipython-input-11-d9162d5dda48> in <module>()
----> 1 c.send(None)
StopIteration:
这回答说,本机协同例程在功能上等同于生成的基于协同的协同。但对于同样的问题,另一个答案则更进一步,解释了它们如何达到不同的目的。
本地coros引发StopIteration
错误的唯一原因是它们与基于生成器的coros共享重要代码吗?还是还有别的原因?
发布于 2018-05-04 01:25:53
我认为在佩普492背后的讨论中,没有人专门讨论过这是一个明确的设计选择,但我认为,这不仅是因为他们碰巧共享了重要的代码,而且他们的意图是尽可能地互换。如果其他的async
实现由于某种原因不同地构建了yield from
coros和yield from
coros,那么它们仍然需要像在CPython中一样可以互换(这样,您就可以运行为Python3.4编写的asyncio
代码)。
无论如何,即使在这么多话中没有明确说明理由,该决定也在协同目标方法下的PEP中得到了明确的记录
协同机制是基于内部的生成器,因此它们共享实现。与生成器对象类似,协同器有
throw()
、send()
和close()
方法。StopIteration
和GeneratorExit
在协同工作中扮演着同样的角色…
作为async for
讨论的一部分,有一件事是异步迭代器不能提高StopIteration
。如果设计被改变了,那么异步迭代器就可以提高它,这就不可能用普通的生成器来构建异步迭代器了。因此,创建了一个新的例外,StopAsyncIteration
。在这一点上,很明显,实际上没有一个coro或普通生成器应该显式地提高StopIteration
,因此佩普479 (它立即应用于异步coros,但在传统生成器中有几个版本)。见StopAsyncIteration
。
https://stackoverflow.com/questions/50165734
复制相似问题