【问题标题】:Native coroutine and StopIteration原生协程和 StopIteration
【发布时间】:2018-10-14 09:34:11
【问题描述】:

考虑这个简单的协程

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:

this 回答原生协程在功能上等同于基于生成的协程。但同一问题的另一个答案更进一步,并解释了它们如何服务于不同的目的。

本机 coros 引发 StopIteration 错误的唯一原因是它们与基于生成器的 coros 共享重要代码吗?还是还有其他原因?

【问题讨论】:

    标签: python asynchronous


    【解决方案1】:

    我认为没有人在 PEP 492 背后的讨论中专门将此作为明确的设计选择进行讨论,但我认为这不仅仅是 他们碰巧共享重要代码,而且他们're 打算尽可能地互换。如果某些其他 Python 实现出于某种原因构建 async coros 和 yield from coros 的方式不同,它们仍然需要像在 CPython 中一样可互换(例如,您可以运行为 Python 编写的 asyncio 代码3.4)。

    无论如何,即使理由并没有在任何地方用这么多的词体现出来,该决定也明确记录在 PEP 中,Coroutine object methods

    协程内部基于生成器,因此它们共享实现。与生成器对象类似,协程具有throw()send()close() 方法。 StopIterationGeneratorExit 在协程中扮演同样的角色……

    作为async for 讨论的一部分,确实 出现的一件事是异步迭代器无法引发StopIteration。如果设计以某种方式被改变,异步迭代器可以提升它,那将不可能用普通的生成器构建异步迭代器。因此,创建了一个新异常 StopAsyncIteration。此时很明显,实际上没有任何情况下 coro 或普通生成器应该显式提高StopIteration,因此PEP 479(它立即应用于异步 coros,但在传统生成器的几个版本中被祖父辈继承) .见Why StopAsyncIteration

    【讨论】:

      猜你喜欢
      • 2023-04-09
      • 2016-03-31
      • 1970-01-01
      • 2015-12-11
      • 2020-02-27
      • 2016-05-29
      • 2018-03-26
      • 2017-03-26
      • 2011-08-22
      相关资源
      最近更新 更多