如何让自定义可等待对象的__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
相关产品推荐
相关产品推荐

