You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让自定义可等待对象的__await__方法与异步函数行为完全一致?

自定义可等待对象__await__方法如何复用异步函数的返回值

你尝试创建自定义可等待对象,希望复用已有异步函数的逻辑,但遇到await 对象时返回值丢失的问题。你的代码如下:

import asyncio

class MyObject:
    async def ten(self):
        await asyncio.sleep(.5)
        print("Returning")
        return 10

    def __await__(self):
         # 尝试复用ten()的逻辑
        yield from self.ten().__await__()

async def main():
    object = MyObject()
    print(await object.ten())
    print(await object)


if __name__ == '__main__':
    asyncio.run(main())

运行后,await object.ten()返回10,但await object返回None。这是因为你的__await__是一个生成器函数,没有显式返回值——当yield from完成后,生成器默认返回None,asyncio无法获取到异步函数ten()的返回值。

要让__await__和指定异步函数行为完全一致(包括返回值),只需要在生成器函数中返回yield from的结果即可:

import asyncio

class MyObject:
    async def ten(self):
        await asyncio.sleep(.5)
        print("Returning")
        return 10

    def __await__(self):
        # 复用ten()的逻辑并返回其结果
        return (yield from self.ten().__await__())

async def main():
    obj = MyObject()
    print(await obj.ten())
    print(await obj)  # 现在会输出10

if __name__ == '__main__':
    asyncio.run(main())

原理说明

在Python生成器中,yield from会传递迭代器的最终返回值。当你在__await__中return (yield from ...)时,生成器会把异步函数ten()的返回值包装到StopIteration异常的value属性中,asyncio处理可等待对象时,会自动提取这个值作为await的结果。

如果需要更通用的写法(适配不同异步函数),也可以用包装异步函数的方式:

def __await__(self):
    async def wrapper():
        return await self.ten()  # 这里可替换为任意异步方法
    return wrapper().__await__()

这种写法更直观,本质和yield from方式等价,都能完整复用异步函数的逻辑和返回值。

内容的提问来源于stack exchange,提问作者Frank Yellin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 11:20:58