python-3.x 在异步生成器上使用next()

vqlkdk9b  于 2022-12-30  发布在  Python
关注(0)|答案(3)|浏览(162)

使用next()内置函数可以逐步迭代生成器。例如:

def sync_gen(n):
    """Simple generator"""
    for i in range(n):
        yield i**2

sg = sync_gen(4)
print(next(sg)) # -> 0
print(next(sg)) # -> 1
print(next(sg)) # -> 4

在异步生成器上使用next()不起作用:

import asyncio

async def async_gen(n):
    for i in range(n):
        yield i**2

async def main():
    print("Async for:")
    async for v in async_gen(4):  # works as expected
        print(v)

    print("Async next:")
    ag = async_gen(4)
    v = await next(ag) # raises: TypeError: 'async_generator' object is not an iterator
    print(v)

asyncio.run(main())

是否存在类似v = await async_next(ag)的东西来获得与正常生成器相同的行为?

xmq68pz9

xmq68pz91#

因为Python 3.10有aiter(async_iterable)awaitable anext(async_iterator)内置函数,类似于iternext,所以你不必再依赖async_iterator.__anext__()魔术方法了,下面这段代码在Python 3.10中是有效的:

import asyncio

async def async_gen(n):
    for i in range(n):
        yield i**2

async def main():
    print("Async next:")
    ag = async_gen(4)
    print(await anext(ag))

asyncio.run(main())
2izufjch

2izufjch2#

如前所述,next不能在异步生成器上工作,因为它不是迭代器。
如果必须使用函数,可以创建一个helper函数,而不是使用__anext__函数outrite:

async def anext(ait):
    return await ait.__anext__()

ag = async_gen(4)
v = await anext(ag)
print(v)

编辑:

从python 3.10开始,他们引入了这个内置函数:anext

pvcm50d1

pvcm50d13#

PEP525异步发生器对象描述__anext__()方法:
agen.__anext__():返回一个awatable,它在等待时执行一次异步生成器迭代。
所以我们可以称之为:

print("Async next:")
ag = async_gen(4)
v = await ag.__anext__()
print(v)

但是,如here所述,不建议这样做

相关问题