Python:除async for外,从async函数的yield获取返回值的其他方法?
异步生成器的取值方法说明
先给你说结论:你贴的示例1和示例2完全用不了,不仅拿不到值还会直接报错。
为啥不行?因为async def搭配yield定义的是异步生成器,它和普通同步生成器的迭代逻辑完全不同:
- 普通生成器用
next()或者__next__()就能触发迭代,是同步操作 - 异步生成器必须用专门的异步迭代方法
__anext__(),而且必须搭配await才能拿到结果
正确的手动逐个取值方式
要是想手动挨个拿yield的值,得这么写:
import asyncio async def test(): yield "One" yield "Two" yield "Three" async def call_test(): x = test() print(await x.__anext__()) # 输出 One print(await x.__anext__()) # 输出 Two print(await x.__anext__()) # 输出 Three # 要是生成器已经没值了,再调用__anext__会抛出StopAsyncIteration异常 asyncio.run(call_test())
其他可行的取值方法
除了async for和上面这种手动调用的方式,还有几种实用的玩法:
- 异步列表推导式
一次性把所有yield的值收集到列表里,省事高效:
async def call_test(): results = [item async for item in test()] print(results) # 输出 ['One', 'Two', 'Three']
- 批量异步处理(适合需要并发操作的场景)
如果每个yield出来的值需要单独做异步处理,可以用asyncio.gather配合:
async def process_item(item): # 这里可以加自定义异步处理逻辑,比如调用其他async函数 return item async def call_test(): gen = test() tasks = [] try: while True: item = await gen.__anext__() tasks.append(asyncio.create_task(process_item(item))) except StopAsyncIteration: # 生成器耗尽时会触发这个异常,跳出循环 pass results = await asyncio.gather(*tasks) print(results) # 输出 ['One', 'Two', 'Three']
补充:示例1、2为啥报错?
运行示例1的代码时,会直接弹出TypeError: 'async_generator' object is not an iterator——因为异步生成器根本没实现同步迭代器的__next__()方法,next()函数也处理不了异步生成器对象,自然拿不到值。
内容的提问来源于stack exchange,提问作者Super Kai - Kazuya Ito
相关产品推荐
相关产品推荐

