Python __await__ 方法
最后修改于 2025 年 4 月 8 日
本综合指南探讨了 Python 的 __await__
方法,这是一个使对象可等待的特殊方法。我们将介绍异步编程、协程、可等待对象以及实践示例。
基本定义
__await__
方法返回一个迭代器,该迭代器用于实现可等待对象。它允许一个对象在异步函数中与 await
表达式一起使用。
主要特征:它必须返回一个迭代器,被 async/await 语法使用,并启用自定义的可等待对象。它是 Python 3.5 中引入的 Python 异步编程模型的一部分。
基本 __await__ 实现
这是一个简单的实现,展示了 __await__
如何使自定义对象可等待。该方法必须返回一个迭代器。
class SimpleAwaitable: def __await__(self): yield return "Done" async def main(): result = await SimpleAwaitable() print(result) # Output: Done import asyncio asyncio.run(main())
此示例创建一个基本的可等待对象。__await__
方法 yield 一次并返回一个值。当被 await 时,它会暂停执行,直到 yield 完成。
yield
至关重要 - 它使该方法成为生成器,这是 __await__
所必需的。返回值成为 await 表达式的结果。
具有异步操作的可等待对象
此示例展示了一个更实用的可等待对象,它模拟了具有延迟的异步操作。
class AsyncOperation: def __init__(self, delay): self.delay = delay def __await__(self): yield from asyncio.sleep(self.delay) return f"Completed after {self.delay}s" async def main(): op = AsyncOperation(1.5) print("Starting operation") result = await op print(result) asyncio.run(main())
此可等待对象使用 asyncio.sleep
来模拟异步操作。yield from
委托给另一个可等待对象。
当被 await 时,它会在返回完成消息之前暂停执行指定的延迟。这种模式对于包装异步操作很常见。
自定义 Future 实现
此示例演示如何使用 __await__
实现一个基本的类似 Future 的对象,该对象可以在以后设置结果。
class CustomFuture: def __init__(self): self._result = None self._done = False def set_result(self, result): self._result = result self._done = True def __await__(self): while not self._done: yield return self._result async def set_future(future, delay, value): await asyncio.sleep(delay) future.set_result(value) async def main(): future = CustomFuture() asyncio.create_task(set_future(future, 2, "Future result")) print("Waiting for future...") result = await future print(f"Got: {result}") asyncio.run(main())
这个 CustomFuture 可以被 await,直到它的结果被设置。__await__
方法 yield,直到 _done
变为 True,然后返回结果。
这模仿了真正的 Futures 在 asyncio 中的工作方式,允许解耦的结果设置和等待。此模式对于将基于回调的 API 与异步连接起来非常有用。
链式可等待对象
此示例展示了如何使用 __await__
将多个可等待对象链接在一起。
class AddAwaitable: def __init__(self, a, b): self.a = a self.b = b def __await__(self): result = yield from self.a.__await__() result += yield from self.b.__await__() return result async def slow_add(a, b): await asyncio.sleep(1) return a + b async def main(): a = slow_add(10, 20) b = slow_add(30, 40) combined = AddAwaitable(a, b) result = await combined print(f"Total: {result}") # Output: Total: 100 asyncio.run(main())
AddAwaitable
类链接了两个可等待对象,并将它们的结果相加。它使用 yield from
依次 await 每个操作数。
这演示了 __await__
如何将多个异步操作组合成新的可等待对象。此模式对于构建复杂的异步工作流非常有用。
带有 __await__ 的异步上下文管理器
此示例使用 __await__
实现了一个异步上下文管理器,用于资源管理。
class AsyncResource: def __init__(self, name): self.name = name async def __aenter__(self): print(f"Opening {self.name}") await asyncio.sleep(0.5) return self async def __aexit__(self, *args): print(f"Closing {self.name}") await asyncio.sleep(0.5) def __await__(self): return self.__aenter__().__await__() async def main(): async with AsyncResource("DB Connection") as resource: print(f"Using {resource.name}") await asyncio.sleep(1) # Alternative using await directly resource = await AsyncResource("File") try: print(f"Using {resource.name}") await asyncio.sleep(1) finally: await resource.__aexit__(None, None, None) asyncio.run(main())
这展示了使用异步资源的两种方法:使用 async with
和直接使用 await
。__await__
方法委托给 __aenter__
。
当您需要上下文管理器和直接 await 支持时,此模式很有用。它演示了 __await__
如何与其他异步协议集成。
最佳实践
- 始终返回一个迭代器:
__await__
必须返回一个迭代器 - 使用 yield 或 yield from: 需要使该方法成为生成器
- 考虑取消: 适当处理 asyncio.CancelledError
- 记录 await 行为: 清楚地记录 await 的作用
- 首选 async def 用于协程: 仅将 __await__ 用于自定义可等待对象
资料来源
作者
列出所有 Python 教程。