【问题标题】:Delegate to a generator in python 3.6+ asyncio coroutine委托给 python 3.6+ asyncio 协程中的生成器
【发布时间】:2018-04-23 21:00:02
【问题描述】:

在 python 3.3 中,我可以执行以下操作

def _gen():
    for i in range(3):
        yield i

def gen():
    yield from _gen()

for i in gen():
    print(i)

>>> 0
>>> 1
>>> 2

我可以在 python 3.6 asyncio 协程中做同样的事情吗? (警告,人为的例子)

async def _gen():
    for i in range(3):
        yield await get_num(i) # get_num is a coroutine

async def gen():
    yield from _gen() # Syntax error!

for i in gen():
    print(i)

我需要将gen 定义为

async def gen():
    async for i in _gen():
        yield i

但似乎应该有一种方法可以像 yield from 那样委托给另一个协程

【问题讨论】:

  • @Vincent 什么表明它将在某个时候实施?
  • 因为这很有意义。这里的限制是,正如 PEP 525 指出的那样,它需要付出一些认真的努力,而且收益非常有限。

标签: python python-3.6 python-asyncio


【解决方案1】:

由于described in PEP 525的原因,Python 3.6不支持yield from

虽然理论上可以实现yield from 支持 异步发电机,这将需要一个认真的重新设计 生成器实现。

yield from 对于异步生成器也不太重要,因为 不需要提供一种机制来实现另一个 协程之上的协程协议。并组成异步 生成器可以使用一个简单的异步 for 循环:

async def g1():
    yield 1
    yield 2

async def g2():
    async for v in g1():
        yield v

【讨论】:

  • 我很难理解为什么yield from 需要对异步生成器的实现方式进行任何形式的更改。不能将yield from 内的async def 简单地脱糖为async for 相当于regular yield from desugaring
  • @user4815162342 我相信异步生成器(和普通生成器)是用 C 实现的,而不是 Python。您提供的链接代码可能只是展示,而不是 CPython 源代码的真实部分。
  • 当然,代码只展示了编译器可以进行的脱糖,实际的实现在字节码求值器中。但是 PEP 声称异步生成器的 实现 需要更改,但没有给出理由。毕竟,yield from 可能只是g2 中显示的那种循环的语法糖。
猜你喜欢
  • 2017-09-02
  • 2011-08-22
  • 1970-01-01
  • 2023-03-27
  • 2020-12-29
  • 1970-01-01
  • 2018-02-10
  • 1970-01-01
  • 2018-02-25
相关资源
最近更新 更多