@asyncio.coroutine vs async def
借助我所见过的
1 2 3 | @asyncio.coroutine def function(): ... |
和
1 2 | async def function(): ... |
可互换使用。
两者之间有功能上的区别吗?
是的,使用
根据PEP 492,它引入了
Native coroutine objects do not implement
__iter__ and
__next__ methods. Therefore, they cannot be iterated over or passed
toiter() ,list() ,tuple() and other built-ins. They also
cannot be used in afor..in loop.An attempt to use
__iter__ or__next__ on a native coroutine
object will result in a TypeError .Plain generators cannot
yield from native coroutines: doing so
will result in a TypeError .generator-based coroutines (for asyncio code must be decorated with
@asyncio.coroutine ) canyield from native coroutine objects.
inspect.isgenerator() andinspect.isgeneratorfunction() returnFalse for native coroutine objects and native coroutine functions.
上面的要点1表示,虽然使用
这是用两种语法定义的两个最小的,表面上等效的协程函数:
1 2 3 4 5 6 7 8 | import asyncio @asyncio.coroutine def decorated(x): yield from x async def native(x): await x |
尽管这两个函数的字节码几乎相同:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | >>> 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 |
...唯一的区别是
1 2 | >>> list(decorated('foo')) ['f', 'o', 'o'] |
1 2 3 4 | >>> list(native('foo')) Traceback (most recent call last): File"<stdin>", line 1, in <module> TypeError: 'coroutine' object is not iterable |
显然,
Brett Cannon对
您可以在
从实际的角度来看,如果您的Python是3.5+,请不要使用
从Python 3.5开始,
在此之前,Python 3.4通过将常规函数包装到