借助我所见过的asyncio库,

@asyncio.coroutine
def function():
    ...


async def function():
    ...

可互换使用。

两者之间有功能上的区别吗?

最佳答案

是的,使用async def语法的本地协程和使用asyncio.coroutine装饰器的基于生成程序的协程之间在功能上存在差异。

根据PEP 492,它介绍了async def语法:



上面的第1点表示,虽然使用@asyncio.coroutine装饰器语法定义的协程函数可以充当传统的生成器函数,但使用async def语法定义的协程函数却不能。

这是用两种语法定义的两个最小的,表面上等效的协程函数:

import asyncio

@asyncio.coroutine
def decorated(x):
    yield from x

async def native(x):
    await x

尽管这两个函数的字节码几乎相同:
>>> import dis
>>> dis.dis(decorated)
  5           0 LOAD_FAST                0 (x)
              3 GET_YIELD_FROM_ITER
              4 LOAD_CONST               0 (None)
              7 YIELD_FROM
              8 POP_TOP
              9 LOAD_CONST               0 (None)
             12 RETURN_VALUE
>>> dis.dis(native)
  8           0 LOAD_FAST                0 (x)
              3 GET_AWAITABLE
              4 LOAD_CONST               0 (None)
              7 YIELD_FROM
              8 POP_TOP
              9 LOAD_CONST               0 (None)
             12 RETURN_VALUE

...唯一的区别是GET_YIELD_FROM_ITERGET_AWAITABLE,当尝试遍历返回的对象时,它们的行为完全不同:
>>> list(decorated('foo'))
['f', 'o', 'o']
>>> list(native('foo'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'coroutine' object is not iterable

显然'foo'并不是可以等待的,因此使用它调用native()的尝试没有多大意义,但是希望可以清楚地知道,无论返回什么coroutine对象,无论其参数如何。

Brett Cannon对async/await语法的更详细研究:How the heck does async/await work in Python 3.5?更深入地涵盖了这种差异。

关于python - @ asyncio.coroutine与异步def,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40571786/

10-12 22:50