@ asyncio.coroutine与异步def
asyncio
我看过的图书馆
@asyncio.coroutine
def function():
...
和
async def function():
...
可互换使用。
两者之间有功能上的区别吗?
-
是的,使用
async def
语法的本地协程和使用asyncio.coroutine
装饰器的基于生成程序的协程之间在功能上有所不同。根据PEP 492引入的
async def
语法:- 原生协程 对象不实现
__iter__
和
__next__
方法。因此,它们不能被遍历或传递给iter()
,list()
,tuple()
和其他内置插件。它们也不能for..in
循环使用。
尝试在本机协程对象上使用
__iter__
或__next__
对本机协程对象进行尝试将导致TypeError。-
普通生成器 无法 生成
yield from
本地协程 :这样做将导致TypeError。 -
基于生成器的协程 (对于异步代码必须用修饰
@asyncio.coroutine
)可以yield from
原生协程对象 。 -
inspect.isgenerator()
并inspect.isgeneratorfunction()
返回False
了
原生协程 对象和 原生协程功能 。
上面的要点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
vsGET_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
语法进行了更详细的研究:异步/等待在Python
3.5中如何工作?涵盖了更深层次的差异。 - 原生协程 对象不实现