Python Language Reference 规定object.__await__如下:
object.__await__(self)必须返回一个迭代器。应该用于实现可等待的对象。例如,
asyncio.Future实现此方法以与 await 表达式兼容。
就是这样。我觉得这个规范很模糊,也不是很具体(讽刺的是)。好的,它应该返回一个迭代器,但它可以是一个任意的迭代器吗?显然不是:
import asyncio
class Spam:
def __await__(self):
yield from range(10)
async def main():
await Spam()
asyncio.run(main())
Run Code Online (Sandbox Code Playgroud)
RuntimeError: Task got bad yield: 0
Run Code Online (Sandbox Code Playgroud)
我假设asyncio事件循环期望迭代器产生特定类型的对象。那么它究竟应该产生什么?(为什么没有记录在案?)
编辑:据我所知,这在任何地方都没有记录。但我一直在调查我自己,我觉得关键是了解哪些对象asyncio预计其协同程序产生在于task_step_impl中_asynciomodule.c。
更新:我做了一个PR与此澄清的目的CPython的库:“明确的模糊规范object.__await__”。目前正在审核中。
我想实现一个 awaitable 并注意到__await__“需要”是一个生成器。
从PEP-492:
具有
__await__返回迭代器的方法的对象。...
__await__在本 PEP 的其余部分中,带有方法的对象称为 Future-like 对象。如果
__await__返回除迭代器以外的任何内容,则为 TypeError 。
根据我的经验,beforeawait是一个语句,yield from与作为生成器实现的协程一起使用。如今,python(我使用的是 3.5)具有使用async def语法的异步方法。因此,我认为该yield from语法是旧的/已弃用的。
所以我打破了解释器,看看这是否有效:
>>> class A:
... def __await__(self):
... yield from (asyncio.sleep(1).__await__())
... return 'spam'
...
>>> a = A()
>>> loop = asyncio.get_event_loop()
>>> loop.run_until_complete(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python3.5/asyncio/base_events.py", line 467, in run_until_complete
return future.result() …Run Code Online (Sandbox Code Playgroud)