Python 异步迭代器完全指南:从同步到异步的优雅转变
开篇:当迭代器遇上异步编程
在 Python 的世界里,迭代器(Iterator)是一个优雅而强大的概念。从简单的 for 循环到复杂的数据流处理,迭代器无处不在。然而,当我们进入异步编程的领域,传统的迭代器就显得力不从心了。
作为一名深耕 Python 异步编程多年的工程师,我见证了从生成器到异步生成器、从迭代器到异步迭代器的演进。今天,我想通过一个经典而有趣的案例——异步斐波那契数列生成器——带你深入理解异步迭代器的设计思想、实现技巧和实战应用。
这不仅仅是一个技术教程,更是一次思维方式的转变之旅。让我们一起探索如何在异步世界中优雅地处理数据流。
一、基础回顾:同步迭代器与生成器
在深入异步迭代器之前,让我们先回顾一下传统的迭代器是如何工作的。
1.1 迭代器协议
Python 的迭代器基于两个核心方法:
class FibonacciIterator:
"""同步斐波那契迭代器"""
def __init__(self, max_count):
self.max_count = max_count
self.count = 0
self.a, self.b = 0, 1
def __iter__(self):
"""返回迭代器对象本身"""
return self
def __next__(self):
"""返回下一个值"""
if self.count >= self.max_count:
raise StopIteration
self.count += 1
current = self.a
self.a, self.b = self.b, self.a + self.b
return current
# 使用示例
fib = FibonacciIterator(10)
for num in fib:
print(num, end=' ')
# 输出: 0 1 1 2 3 5 8 13 21 34
1.2 生成器:更优雅的实现
使用生成器,我们可以用更简洁的方式实现相同功能:
def fibonacci_generator(max_count):
"""同步斐波那契生成器"""
a, b = 0, 1
count = 0
while count < max_count:
yield a
a, b = b, a + b
count += 1
# 使用方式完全相同
for num in fibonacci_generator(10):
print(num, end=' ')
# 输出: 0 1 1 2 3 5 8 13 21 34
生成器的优势:
- 代码更简洁,无需手动维护状态
- 惰性计算,节省内存
- 自动实现了迭代器协议
1.3 同步迭代器的局限
现在,让我们尝试在生成每个数字前等待 0.1 秒:
import time
def slow_fibonacci(max_count):
"""带延迟的同步斐波那契生成器"""
a, b = 0, 1
count = 0
while count < max_count:
time.sleep(0.1) # 模拟耗时操作
yield a
a, b = b, a + b
count += 1
# 问题:这会阻塞整个程序!
start = time.time()
for num in slow_fibonacci(10):
print(f"生成数字: {
num}")
elapsed = time.time() - start
print(f"\n总耗时: {
elapsed:.2f} 秒") # 约 1 秒
在这个例子中,time.sleep(0.1) 会完全阻塞程序执行,无法并发处理其他任务。在现代异步应用中,这是不可接受的。
二、异步迭代器:优雅的解决方案
2.1 异步迭代器协议
Python 3.5 引入了异步迭代器,通过 __aiter__() 和 __anext__() 方法实现:
import asyncio
class AsyncFibonacciIterator:
"""异步斐波那契迭代器"""
def __init__(self, max_count):
self.max_count = max_count
self.count = 0
self.a, self.b = 0, 1
def __aiter__(self):
"""返回异步迭代器对象本身"""
return self
async def __anext__(self):
"""异步返回下一个值"""
if self.count >= self.max_count:
raise StopAsyncIteration
# 异步等待,不会阻塞事件循环
await asyncio.sleep(0.1)
self.count += 1
current = self.a
self.a, self.b = self.b, self.a + self.b
return current
# 使用异步迭代器
async def main():
start = asyncio.get_event_loop().time()
async for num in AsyncFibonacciIterator(10):
print(f"生成数字: {
num}")
elapsed = asyncio.get_event_loop().time() - start
print(f"\n总耗时: {
elapsed:.2f} 秒")
asyncio.r


2116

被折叠的 条评论
为什么被折叠?



