为什么我要在`@asyncio.coroutine`上使用`async def`?

时间:2016-11-13 19:05:22

标签: python python-3.x asynchronous async-await backwards-compatibility

Python 3.5使用新的函数定义语法极大地扩展了对异步编程的支持。而异步函数以前只是"生成器带有好处":

def generate_numbers():
    """
    Generator function that lazily returns 1 - 100
    """
    for i in range 100:
        yield i

generate_async = asyncio.coroutine(generate_numbers)
generate_async.__doc__ = """
    Coroutine that lazily returns 1 - 100
    This can be used interchangeably as a generator or a coroutine
    """

他们现在有自己的特殊声明语法和特殊行为,它们不再像通常的生成器函数那样可用:

aysnc def generate_async_native():
    """
    A coroutine that returns 1 - 100
    This CANNOT be used as a generator, and can ONLY be executed by running it from an event loop
    """
    for i in range(100):
        await i

这是 关于这些类型之间功能或实际差异的问题 - 在this StackOverflow answer中讨论过。

我的问题是:为什么我要使用async def?似乎它没有提供超过@asyncio.coroutine的额外好处,但是因此增加了成本

  1. 打破向后兼容性(Python 3.5代码与async def 在旧版本中甚至解析,虽然这可以说是一个功能,而不是一个bug)和
  2. 似乎在如何调用函数方面提供的灵活性较低。

1 个答案:

答案 0 :(得分:4)

Martijn Pieters给出了一个可能的答案:

  

优点是,通过本机支持,您还可以引入其他语法来支持异步上下文管理器和迭代器。进入和退出上下文管理器,或循环遍历迭代器,然后可以在您的协同例程中成为更多的点,表明其他代码可以运行而不是因为某些事情再次等待

事实上,这已经取得了新的async withasync for语法的实现,而这种语法无法通过"大键盘来实现。像装饰发电机一样的解决方案。