python @ coco.coroutine vs coco def

kyks70gy  于 12个月前  发布在  Python
关注(0)|答案(4)|浏览(122)

使用我见过的asyncio库,

@asyncio.coroutine
def function():
    ...

字符串

async def function():
    ...


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

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语法定义的协程函数却不能。
    下面是两个最小的、表面上等价的协程函数,它们是用两种语法定义的:
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_ITERGET_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?更深入地介绍了这种差异。

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成为执行异步任务的新标准和首选方式。
下面是一个简单的异步函数:

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

字符串

相关问题