在Python中,迭代器是一种可以逐个返回元素的对象,它遵循迭代器协议,而生成器是创建迭代器的一种更简洁的方式,两者在处理大量数据或流式数据时能大幅降低内存占用。

迭代器的基本使用
迭代器的定义与判断
迭代器是实现了__iter__()和__next__()方法的对象,其中__iter__()返回迭代器自身,__next__()返回下一个元素,没有元素时抛出StopIteration异常。可以通过内置的iter()函数将可迭代对象转换为迭代器。
# 判断对象是否为迭代器 from collections.abc import Iterator my_list = [1, 2, 3] my_iter = iter(my_list) print(isinstance(my_list, Iterator)) # 输出 False,列表是可迭代对象不是迭代器 print(isinstance(my_iter, Iterator)) # 输出 True,转换后是迭代器
自定义迭代器
我们可以通过自定义类实现迭代器协议,下面是一个返回指定范围数字的自定义迭代器示例:
class RangeIterator:
def __init__(self, max_num):
self.max_num = max_num
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current < self.max_num:
result = self.current
self.current += 1
return result
else:
raise StopIteration
# 使用自定义迭代器
ri = RangeIterator(5)
for num in ri:
print(num) # 依次输出 0 1 2 3 4
生成器的使用与特性
生成器的基本语法
生成器不需要像迭代器那样手动实现两个方法,有两种常见创建方式:生成器函数和生成器表达式。生成器函数使用yield关键字返回元素,每次调用next()会执行到下一个yield位置暂停。
# 生成器函数示例
def my_generator(max_num):
current = 0
while current < max_num:
yield current
current += 1
gen = my_generator(5)
print(next(gen)) # 输出 0
print(next(gen)) # 输出 1
# 生成器表达式示例,语法类似列表推导式但用圆括号
gen_expr = (x * 2 for x in range(3))
for val in gen_expr:
print(val) # 依次输出 0 2 4
生成器与迭代器的对比
生成器属于迭代器的一种,但是比普通迭代器更简洁,两者的核心差异如下:
| 对比项 | 普通迭代器 | 生成器 |
|---|---|---|
| 实现方式 | 需要自定义类实现__iter__和__next__方法 | 使用yield关键字或生成器表达式,语法更简洁 |
| 内存占用 | 需要手动维护状态变量 | 自动保存执行状态,无需额外定义状态变量 |
| 代码复杂度 | 代码量相对较多 | 代码量少,逻辑更清晰 |
生成器的实际应用场景
处理大文件读取
当读取超大文件时,如果一次性将文件内容加载到内存会导致内存溢出,使用生成器可以逐行读取,降低内存占用:
def read_large_file(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
while True:
line = f.readline()
if not line:
break
yield line.strip()
# 逐行处理文件内容
for line in read_large_file('test.txt'):
print(line)
实现数据流式处理
在需要生成无限序列或者流式数据的场景中,生成器也非常适用,比如生成斐波那契数列:
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
# 获取前10个斐波那契数
for _ in range(10):
print(next(fib), end=' ') # 输出 0 1 1 2 3 5 8 13 21 34
在实际开发中,优先选择生成器来实现迭代逻辑,不仅可以减少代码量,还能让程序的内存使用更高效,尤其是在处理大规模数据或者流式数据的场景中,优势会更加明显。