是的,使用
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装饰器语法定义的协程函数可以像传统的生成器函数一样工作,但使用该语法定义的协程函数
asyncdef不能。
这是用两种语法定义的两个最小的,表面上等效的协程函数:
import [email protected] decorated(x): yield from xasync def native(x): await x
尽管这两个函数的字节码几乎相同:
>>> import dis>>> dis.dis(decorated) 50 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) 80 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_ITERvs
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语法进行了更详细的研究:异步/等待在Python
3.5中如何工作?涵盖了更深层次的差异。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)