借助我所见过的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_ITER
与GET_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/