从generatorbased转换为本地协同程序

2024-10-01 09:28:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经使用Python很多年了,但只是逐渐地研究了该语言更模糊的特性,因为我的大部分代码都是用于数据处理的。基于yield的生成器是我的例程工具箱的一部分,最近我读到了关于协同例程的内容。我发现了一个类似的例子:

def averager():
    sum = 0.0
    n = 0
    while True:
        value = yield
        sum += value
        n += 1
        print(sum/n)

avg = averager()
next(avg) # prime the coroutine
avg.send(3)
avg.send(4)
avg.send(5)

它打印发送给它的值的平均值。我觉得这样的东西在数据处理管道中可能会有用,所以我决定把它放在脑后。也就是说,直到我在Python documentation中读到以下通知:

Support for generator-based coroutines is deprecated and is scheduled for removal in Python 3.10.

显然,我想写未来的证明代码,所以在这一点上,开始学习基于生成器的协同程序可能是无用的。那么,我的问题是:如何使用本机(asyncio)协程实现这个示例?我很难理解本地协同程序语法。你知道吗

在尝试搜索答案时,我发现了一个related question,它有一个comment和一个answer,基本上是说“你不能用async做它,而是用基于yield的协程做它”。但是如果这些都消失了,有没有什么方法可以用3.10+中的协同程序来实现呢?你知道吗


Tags: 代码send语言forisvalue特性例程
1条回答
网友
1楼 · 发布于 2024-10-01 09:28:32

来了Asynchronous Generators。。。你知道吗

因此,在异步上下文中,我们仍然有这种能力
至于理论-提到的PEP 525提供了一个很好的描述,绝对值得一读。
例如,用cdem(I'm>safe)完成异步初始化:

import asyncio

async def coro():
    print('running other coroutine in 3 sec ...')
    await asyncio.sleep(3)  # emulate working


async def averager():
    sum_ = n = 0
    while True:
        v = yield
        sum_ += v
        n += 1
        print(sum_ / n)
        await asyncio.sleep(0.1)


async def main():
    agen = averager()
    await agen.asend(None)
    print(agen.__name__, 'initialized ...')

    await agen.asend(3)
    print('another separate processing here ...')

    await coro()

    await agen.asend(4)
    await agen.asend(14)


loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(main())
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

程序输出:

averager initialized ...
3.0
another separate processing here ...
running other coroutine in 3 sec ...
3.5
7.0

相关问题 更多 >