Python 迭代器和生成器
迭代器和生成器是 Python 中用于处理数据序列的强大且高效的工具。它们允许你按需处理数据,而不是一次性将所有数据加载到内存中,这在处理大数据集时尤其有用。
迭代器 (Iterators)
迭代器是一个表示数据流的对象。它实现了迭代器协议,该协议包含两个方法:__iter__() 和 __next__()。
- 可迭代对象 (Iterable): 任何可以被
for循环遍历的对象都是可迭代对象,例如列表、元组、字符串。当你对一个可迭代对象使用iter()函数时,你会得到一个迭代器。 - 迭代器 (Iterator): 迭代器对象负责在循环中一次返回一个元素。它使用
next()函数来获取下一个值。当没有更多数据时,next()会引发StopIteration异常,for循环会自动捕获这个异常并结束循环。
for 循环的内部工作原理:
python
my_list = [1, 2, 3]
# 1. for 循环首先调用 iter() 获取迭代器
my_iterator = iter(my_list)
# 2. 然后循环调用 next() 获取每个元素
print(next(my_iterator)) # 输出: 1
print(next(my_iterator)) # 输出: 2
print(next(my_iterator)) # 输出: 3
# 3. 当元素耗尽时,引发 StopIteration
# print(next(my_iterator)) # StopIteration迭代器是“一次性”的。一旦你遍历完一个迭代器,它就耗尽了,不能再次使用。
生成器 (Generators)
生成器是一种特殊类型的迭代器,但你不需要手动创建类来实现 __iter__() 和 __next__() 方法。创建生成器有两种主要方式:
1. 生成器函数
生成器函数是一个使用 yield 关键字的函数。当你调用一个生成器函数时,它不会立即执行,而是返回一个生成器对象(它也是一个迭代器)。
每次在生成器上调用 next() 时,函数会执行到 yield 语句处,yield 会“产出”一个值,然后函数会暂停执行,并保存其当前状态(包括局部变量和指令指针)。下次再调用 next() 时,函数会从上次暂停的地方继续执行。
示例:
python
def simple_generator():
print("Generator started")
yield 1
print("Generator resumed")
yield 2
print("Generator resumed again")
yield 3
print("Generator finished")
# 创建生成器对象
gen = simple_generator()
# 逐个获取值
print(next(gen))
# 输出:
# Generator started
# 1
print(next(gen))
# 输出:
# Generator resumed
# 2
# 也可以用 for 循环遍历
for value in simple_generator():
print(f"For loop got: {value}")2. 生成器表达式
生成器表达式提供了一种更简洁的方式来创建生成器,其语法类似于列表推导式,但使用圆括号 () 而不是方括号 []。
python
# 列表推导式:立即创建完整列表,占用内存
my_list = [x*x for x in range(5)]
print(my_list) # 输出: [0, 1, 4, 9, 16]
# 生成器表达式:创建一个生成器对象,按需生成值,节省内存
my_generator = (x*x for x in range(5))
print(my_generator) # 输出: <generator object <genexpr> at ...>
# 遍历生成器来获取值
for value in my_generator:
print(value)
# 输出: 0, 1, 4, 9, 16为什么使用生成器?
- 内存效率: 生成器按需生成值,不会一次性在内存中存储整个序列。这使得处理非常大(甚至是无限)的数据流成为可能。
- 代码简洁: 生成器函数和表达式比手动创建迭代器类要简单得多。
- 可读性强: 它们清晰地表达了数据是如何按序列生成的逻辑。