Python 迭代器与生成器详解
在 Python 中,迭代器(Iterator)和生成器(Generator)是处理序列数据的关键工具,它们支持高效、惰性计算(按需生成值),尤其适合处理大数据或无限序列。以下是详细解析:
一、迭代器(Iterator)
1. 核心概念
- 迭代器协议:任何实现了
__iter__()
和__next__()
方法的对象都是迭代器。 - 惰性计算:迭代器逐个返回值,不预存所有数据,节省内存。
- 状态性:迭代器记录当前位置,迭代一次后不可逆。
2. 创建迭代器
手动实现迭代器类
class CountDown:
def __init__(self, start):
self.current = start
def __iter__(self):
return self # 返回迭代器自身
def __next__(self):
if self.current <= 0:
raise StopIteration # 终止条件
else:
self.current -= 1
return self.current + 1
# 使用
counter = CountDown(3)
for num in counter:
print(num) # 输出 3, 2, 1
内置迭代器
列表、字符串、字典等可迭代对象通过 iter()
转换为迭代器:
my_list = [1, 2, 3]
my_iter = iter(my_list)
print(next(my_iter)) # 1
print(next(my_iter)) # 2
3. 使用场景
- 遍历大型数据集(如文件逐行读取,无需全部加载到内存):
with open('data.txt') as f:
for line in f: # 文件对象本身是迭代器
process(line)
- 自定义复杂迭代逻辑(如分页数据加载)。
二、生成器(Generator)
1. 核心概念
- 生成器是迭代器:生成器自动实现迭代器协议(
__iter__
和__next__
)。 - 惰性生成值:使用
yield
关键字暂停函数,保留状态,下次继续执行。 - 内存高效:适合生成无限序列或大规模数据。
2. 创建生成器
生成器函数(通过 yield
)
def count_down(start):
current = start
while current > 0:
yield current # 暂停并返回值
current -= 1
gen = count_down(3)
for num in gen:
print(num) # 3, 2, 1
生成器表达式(类似列表推导式,用圆括号)
squares = (x**2 for x in range(5))
print(list(squares)) # [0, 1, 4, 9, 16]
3. 高级用法
双向通信:使用 send()
向生成器发送数据
def accumulator():
total = 0
while True:
value = yield total # yield返回total,并接收外部send的值
total += value
gen = accumulator()
next(gen) # 启动生成器
print(gen.send(10)) # 10
print(gen.send(20)) # 30
无限序列
def infinite_sequence():
num = 0
while True:
yield num
num += 1
for n in infinite_sequence():
if n > 100:
break
print(n)
4. 使用场景
- 处理大规模数据流(如日志文件分析):
def read_large_file(file_path):
with open(file_path) as f:
for line in f:
yield line.strip()
for line in read_large_file('bigfile.log'):
process(line)
- 生成无限序列(如斐波那契数列):
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
print([next(fib) for _ in range(10)]) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
- 实现协程(Coroutine):生成器可用于简单的并发编程(需结合事件循环)。
三、迭代器 vs 生成器:核心区别
特性 | 迭代器 | 生成器 |
---|---|---|
实现方式 | 手动定义 __iter__ 和 __next__ |
使用 yield 或生成器表达式 |
内存占用 | 可能占用较多内存(需存储状态) | 极低(动态生成值) |
代码简洁性 | 需要完整类定义 | 更简洁(函数或一行表达式) |
适用场景 | 需要精细控制迭代逻辑 | 快速生成序列或处理大数据 |
四、最佳实践
- 优先使用生成器:代码更简洁,内存更高效。
- 避免多次迭代:生成器和迭代器只能遍历一次。
- 处理大文件:用生成器逐行读取,避免内存溢出。
- 无限序列:只能用生成器(如传感器数据流)。
五、示例总结
迭代器示例:自定义分页加载
class Paginator:
def __init__(self, data, page_size):
self.data = data
self.page_size = page_size
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index >= len(self.data):
raise StopIteration
page = self.data[self.index : self.index + self.page_size]
self.index += self.page_size
return page
pages = Paginator(list(range(10)), 3)
for page in pages:
print(page) # [0,1,2], [3,4,5], [6,7,8],
生成器示例:过滤数据流
def filter_negative(numbers):
for n in numbers:
if n >= 0:
yield n
data_stream = (x for x in [-5, 3, -2, 0, 8])
positive_gen = filter_negative(data_stream)
print(list(positive_gen)) # [3, 0, 8]
掌握迭代器和生成器,可以显著提升代码性能和可维护性,尤其在处理大规模或动态数据时。