__等待_需要成为发电机吗?

本教程将介绍__等待_需要成为发电机吗?的处理方法,这篇教程是从别的地方看到的,然后加了一些国外程序员的疑问与解答,希望能对你有所帮助,好了,下面开始学习吧。

__等待_需要成为发电机吗? 教程 第1张

问题描述

我要实现一个可等待的,并注意到__await__‘需要’成为一个生成器。

发件人PEP-492:

具有返回迭代器的__await__方法的对象。

...

在本PEP的其余部分中,使用__await__方法的对象称为类Future对象。

如果__await__返回的不是迭代器,则为TypeError。

根据我的经验,在await成为语句之前,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()
  File "/usr/lib64/python3.5/asyncio/futures.py", line 294, in result
 raise self._exception
  File "/usr/lib64/python3.5/asyncio/tasks.py", line 240, in _step
 result = coro.send(None)
  File "/usr/lib64/python3.5/asyncio/tasks.py", line 585, in _wrap_awaitable
 return (yield from awaitable.__await__())
  File "<stdin>", line 3, in __await__
AttributeError: 'generator' object has no attribute '__await__'

因此,asyncio.sleep似乎没有__await__方法。使用这种yield from语法也感觉很别扭。

所以我决定尝试async语法,看看它是否有效:

>>> class A:
...  async def __await__(self):
...await asyncio.sleep(1)
...return 'spam'
... 
>>> a = A()
>>> 
>>> loop = asyncio.get_event_loop()
>>> loop.run_until_complete(a)
'spam'

它似乎真的起作用了!所以现在我想知道,__await__方法是否真的需要成为使用yield from语法的生成器?


编辑:当添加一个间接级别时,因此在await语句中使用可等待值时,问题变得很明显:

>>> async def test():
...  return await A()
... 
>>> loop.run_until_complete(test())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/asyncio/base_events.py", line 387, in run_until_complete
 return future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
 raise self._exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
 result = coro.send(None)
  File "<stdin>", line 2, in test
TypeError: __await__() returned a coroutine

因此它实际上需要返回一个生成器,如下所示:

class A:
 def __await__(self):
  yield from asyncio.sleep(1)
  return 'spam' 

推荐答案

因此看起来asyncio.sleep没有__await__方法

没错,但它不一定要有一个才能等待。documentation表示,如果存在__await__,则需要返回迭代器,而不是await将只对定义__await__的对象起作用。事实上,它显式地记录了await的参数可以是:

之一

    A对象。

    types.coroutine()修饰的函数返回的基于生成器的协程对象。

    具有返回迭代器的__await__方法的对象。

    /li>

    用C定义的对象,提供与__await__特殊方法等效的Python/C。

所以现在我想知道,__await__方法真的需要成为使用Year From语法的生成器吗?

如果您实际有__await__方法,则它确实需要返回迭代器。

好了关于__等待_需要成为发电机吗?的教程就到这里就结束了,希望趣模板源码网找到的这篇技术文章能帮助到大家,更多技术教程可以在站内搜索。