python @ coco.coroutine vs coco def

kyks70gy  于 2024-01-05  发布在  Python
关注(0)|答案(4)|浏览(160)

使用我见过的asyncio库,

  1. @asyncio.coroutine
  2. def function():
  3. ...

字符串

  1. async def function():
  2. ...


互换使用
两者在功能上有什么区别吗?

z0qdvdin

z0qdvdin1#

是的,使用async def语法的原生协程和使用asyncio.coroutine装饰器的基于生成器的协程之间存在功能差异。
根据PEP 492,它引入了async def语法:
1.* 本机协程 * 对象不实现__iter____next__方法。因此,它们不能迭代或传递给iter()list()tuple()和其他内置程序。它们也不能在for..in循环中使用。
尝试在本机协程对象上使用__iter____next__将导致TypeError。
1.* 普通生成器 * 不能yield from * 原生协程 :这样做会导致TypeError。
1.
基于生成器的协程 *(对于Pencio代码必须用@asyncio.coroutine修饰)可以yield from * 原生协程对象 *。

  1. inspect.isgenerator()inspect.isgeneratorfunction()native coroutine 对象和 *native coroutine函数 * 返回False
    上面的第1点意味着,虽然使用@asyncio.coroutine装饰器语法定义的协程函数可以像传统的生成器函数一样工作,但使用async def语法定义的协程函数却不能。
    下面是两个最小的、表面上等价的协程函数,它们是用两种语法定义的:
  1. import asyncio
  2. @asyncio.coroutine
  3. def decorated(x):
  4. yield from x
  5. async def native(x):
  6. await x

字符串
虽然这两个函数的字节码几乎相同:

  1. >>> import dis
  2. >>> dis.dis(decorated)
  3. 5 0 LOAD_FAST 0 (x)
  4. 3 GET_YIELD_FROM_ITER
  5. 4 LOAD_CONST 0 (None)
  6. 7 YIELD_FROM
  7. 8 POP_TOP
  8. 9 LOAD_CONST 0 (None)
  9. 12 RETURN_VALUE
  10. >>> dis.dis(native)
  11. 8 0 LOAD_FAST 0 (x)
  12. 3 GET_AWAITABLE
  13. 4 LOAD_CONST 0 (None)
  14. 7 YIELD_FROM
  15. 8 POP_TOP
  16. 9 LOAD_CONST 0 (None)
  17. 12 RETURN_VALUE


.唯一的区别是GET_YIELD_FROM_ITERGET_AWAITABLE,当试图覆盖它们返回的对象时,它们的行为完全不同:

  1. >>> list(decorated('foo'))
  2. ['f', 'o', 'o']

  1. >>> list(native('foo'))
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. TypeError: 'coroutine' object is not iterable


显然,'foo'不是一个可等待的对象,所以尝试用它来调用native()没有多大意义,但重点是希望它返回的coroutine对象是不可迭代的,不管它的参数是什么。
Brett Cannon对async/await语法进行了更详细的研究:How the heck does async/await work in Python 3.5?更深入地介绍了这种差异。

展开查看全部
cwtwac6a

cwtwac6a2#

async def是Python 3.5中的新语法。您可以在async def s中使用awaitasync withasync for
@coroutineasync def的函数类似物,但它在Python 3.4+中工作,并使用yield from构造而不是await
实际上,如果你的Python是3.5+,就不要使用@coroutine

hi3rlvi2

hi3rlvi23#

Python 3.5开始,coroutines正式成为一种独特的类型,因此async def语法,沿着出现await语句。
在此之前,Python 3.4 通过将常规函数 Package 到generators中来创建协程,因此使用了装饰器语法,以及更像生成器的yield from

ljsrvy3e

ljsrvy3e4#

在Python 3.4中,当原生协程不可用时,异步编程是使用@asyncio.coroutine实现的,它使用yield from语法来暂停和恢复生成器以执行异步任务。
然而,在Python 3.5中,引入了原生协程的概念,它使用async def来定义协程,可以使用await暂停协程。这允许在不阻塞事件循环的情况下有效地暂停执行,从而提高性能。
因此,async def成为执行异步任务的新标准和首选方式。
下面是一个简单的异步函数:

  1. async def my_coroutine():
  2. await fetch_db_record() # some asynchronous function

字符串

相关问题