Appearance
Python 迭代器与生成器
迭代器和生成器是 Python 中处理可迭代对象的重要概念。本章节将详细介绍 Python 中的迭代器和生成器。
迭代器
迭代器是一个实现了 __iter__() 和 __next__() 方法的对象。它可以逐个返回元素,直到没有元素可返回时抛出 StopIteration 异常。
迭代器协议
迭代器协议是指对象必须实现以下两个方法:
__iter__():返回迭代器对象本身。__next__():返回下一个元素,如果没有更多元素,则抛出StopIteration异常。
创建迭代器
可以通过以下两种方式创建迭代器:
- 使用内置的
iter()函数将可迭代对象转换为迭代器。 - 自定义一个实现了迭代器协议的类。
使用 iter() 函数
示例:
python
# 使用 iter() 函数创建迭代器
# 列表
my_list = [1, 2, 3, 4, 5]
iter_list = iter(my_list)
print(next(iter_list)) # 输出:1
print(next(iter_list)) # 输出:2
print(next(iter_list)) # 输出:3
print(next(iter_list)) # 输出:4
print(next(iter_list)) # 输出:5
# print(next(iter_list)) # 抛出 StopIteration 异常
# 字符串
my_string = "hello"
iter_string = iter(my_string)
print(next(iter_string)) # 输出:h
print(next(iter_string)) # 输出:e
print(next(iter_string)) # 输出:l
print(next(iter_string)) # 输出:l
print(next(iter_string)) # 输出:o
# print(next(iter_string)) # 抛出 StopIteration 异常
# 元组
my_tuple = (1, 2, 3)
iter_tuple = iter(my_tuple)
print(next(iter_tuple)) # 输出:1
print(next(iter_tuple)) # 输出:2
print(next(iter_tuple)) # 输出:3
# print(next(iter_tuple)) # 抛出 StopIteration 异常自定义迭代器
示例:
python
# 自定义迭代器
class MyIterator:
def __init__(self, start, end):
self.current = start
self.end = end
def __iter__(self):
return self
def __next__(self):
if self.current < self.end:
value = self.current
self.current += 1
return value
else:
raise StopIteration
# 使用自定义迭代器
my_iter = MyIterator(1, 5)
print(next(my_iter)) # 输出:1
print(next(my_iter)) # 输出:2
print(next(my_iter)) # 输出:3
print(next(my_iter)) # 输出:4
# print(next(my_iter)) # 抛出 StopIteration 异常
# 在 for 循环中使用迭代器
print("\n在 for 循环中使用迭代器:")
my_iter = MyIterator(1, 5)
for num in my_iter:
print(num, end=" ") # 输出:1 2 3 4
print()
# 再次使用迭代器(需要重新创建)
print("\n再次使用迭代器:")
my_iter = MyIterator(1, 5)
for num in my_iter:
print(num, end=" ") # 输出:1 2 3 4
print()迭代器的特点
- 一次性:迭代器只能遍历一次,遍历完后需要重新创建。
- 惰性计算:迭代器按需生成元素,节省内存。
- 不可回退:迭代器只能向前移动,不能回退。
- 可迭代:迭代器本身是可迭代的,因为它实现了
__iter__()方法。
示例:
python
# 迭代器的特点
# 一次性
print("迭代器的一次性:")
my_list = [1, 2, 3]
iter_list = iter(my_list)
print(list(iter_list)) # 输出:[1, 2, 3]
print(list(iter_list)) # 输出:[](已遍历完)
# 惰性计算
print("\n迭代器的惰性计算:")
# 生成器表达式是一种惰性计算
my_generator = (i**2 for i in range(1000000))
print("生成器已创建,但尚未计算元素")
print(next(my_generator)) # 输出:0(按需计算)
print(next(my_generator)) # 输出:1(按需计算)
# 不可回退
print("\n迭代器的不可回退:")
my_list = [1, 2, 3]
iter_list = iter(my_list)
print(next(iter_list)) # 输出:1
print(next(iter_list)) # 输出:2
# 无法回到上一个元素
print(next(iter_list)) # 输出:3
# 可迭代
print("\n迭代器的可迭代性:")
my_list = [1, 2, 3]
iter_list = iter(my_list)
print(iter(iter_list) is iter_list) # 输出:True(迭代器的 __iter__() 方法返回自身)生成器
生成器是一种特殊的迭代器,它使用 yield 语句来返回元素,而不是 return 语句。生成器更加简洁、高效,是创建迭代器的首选方式。
创建生成器
可以通过以下两种方式创建生成器:
- 使用生成器表达式。
- 定义一个包含
yield语句的函数。
生成器表达式
生成器表达式与列表推导式类似,但使用圆括号 () 而不是方括号 []。
示例:
python
# 生成器表达式
# 基本用法
print("基本用法:")
gen = (i**2 for i in range(5))
print(gen) # 输出:<generator object <genexpr> at 0x...>
# 遍历生成器
for num in gen:
print(num, end=" ") # 输出:0 1 4 9 16
print()
# 带条件的生成器表达式
print("\n带条件的生成器表达式:")
gen = (i for i in range(10) if i % 2 == 0)
for num in gen:
print(num, end=" ") # 输出:0 2 4 6 8
print()
# 复杂表达式的生成器表达式
print("\n复杂表达式的生成器表达式:")
words = ["hello", "world", "python"]
gen = (word.upper() for word in words)
for word in gen:
print(word, end=" ") # 输出:HELLO WORLD PYTHON
print()生成器函数
生成器函数是一个包含 yield 语句的函数,调用时返回一个生成器对象。
示例:
python
# 生成器函数
def my_generator():
yield 1
yield 2
yield 3
yield 4
yield 5
# 使用生成器函数
gen = my_generator()
print(gen) # 输出:<generator object my_generator at 0x...>
# 遍历生成器
print("遍历生成器:")
for num in gen:
print(num, end=" ") # 输出:1 2 3 4 5
print()
# 再次使用生成器(需要重新调用函数)
print("\n再次使用生成器:")
gen = my_generator()
for num in gen:
print(num, end=" ") # 输出:1 2 3 4 5
print()yield 语句
yield 语句的作用是:
- 暂停函数执行,返回当前值。
- 保存函数的状态,下次调用时从暂停的地方继续执行。
示例:
python
# yield 语句的工作原理
def count_up_to(n):
print("开始计数")
i = 0
while i < n:
print(f"准备返回 {i}")
yield i
i += 1
print(f"继续执行,i = {i}")
print("计数结束")
# 使用生成器
gen = count_up_to(3)
print("生成器已创建")
print("\n第一次调用 next():")
print(next(gen)) # 输出:开始计数 准备返回 0 0
print("\n第二次调用 next():")
print(next(gen)) # 输出:继续执行,i = 1 准备返回 1 1
print("\n第三次调用 next():")
print(next(gen)) # 输出:继续执行,i = 2 准备返回 2 2
print("\n第四次调用 next():")
try:
print(next(gen)) # 输出:继续执行,i = 3 计数结束
except StopIteration:
print("StopIteration 异常")生成器的特点
- 惰性计算:生成器按需生成元素,节省内存。
- 一次性:生成器只能遍历一次,遍历完后需要重新创建。
- 状态保存:生成器保存函数的状态,下次调用时从暂停的地方继续执行。
- 简洁高效:生成器代码更加简洁、高效,是创建迭代器的首选方式。
示例:
python
# 生成器的特点
# 惰性计算
print("生成器的惰性计算:")
def infinite_sequence():
i = 0
while True:
yield i
i += 1
# 创建生成器
gen = infinite_sequence()
print("生成器已创建,不会立即执行")
# 按需生成元素
print(next(gen)) # 输出:0
print(next(gen)) # 输出:1
print(next(gen)) # 输出:2
# 状态保存
print("\n生成器的状态保存:")
def countdown(n):
while n > 0:
yield n
n -= 1
gen = countdown(3)
print(next(gen)) # 输出:3
print("暂停执行")
print(next(gen)) # 输出:2
print("暂停执行")
print(next(gen)) # 输出:1
# 简洁高效
print("\n生成器的简洁高效:")
# 生成器表达式
print("生成器表达式:")
gen = (i**2 for i in range(10))
print(list(gen)) # 输出:[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 生成器函数
print("\n生成器函数:")
def squares(n):
for i in range(n):
yield i**2
gen = squares(10)
print(list(gen)) # 输出:[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]生成器的高级特性
send() 方法
生成器的 send() 方法用于向生成器发送一个值,并继续执行生成器,返回下一个 yield 语句的结果。
示例:
python
# send() 方法
def echo_generator():
print("生成器已启动")
while True:
received = yield
print(f"收到:{received}")
# 创建生成器
gen = echo_generator()
# 启动生成器(第一次调用 next() 或 send(None))
next(gen) # 输出:生成器已启动
# 发送值
gen.send("Hello") # 输出:收到:Hello
gen.send("World") # 输出:收到:World
# 关闭生成器
gen.close()
# 再次发送值会抛出异常
# gen.send("Python") # StopIterationthrow() 方法
生成器的 throw() 方法用于向生成器抛出一个异常,并继续执行生成器,返回下一个 yield 语句的结果。
示例:
python
# throw() 方法
def error_generator():
try:
yield 1
yield 2
yield 3
except ValueError as e:
print(f"捕获到 ValueError:{e}")
yield 4
yield 5
finally:
print("生成器结束")
# 创建生成器
gen = error_generator()
# 正常执行
print(next(gen)) # 输出:1
print(next(gen)) # 输出:2
# 抛出异常
print(gen.throw(ValueError, "测试错误")) # 输出:捕获到 ValueError:测试错误 4
# 继续执行
print(next(gen)) # 输出:5
# 再次调用会抛出 StopIteration
# print(next(gen)) # 输出:生成器结束 StopIterationclose() 方法
生成器的 close() 方法用于关闭生成器,释放资源。关闭后再次调用 next() 或 send() 会抛出 StopIteration 异常。
示例:
python
# close() 方法
def my_generator():
try:
yield 1
yield 2
yield 3
finally:
print("生成器已关闭")
# 创建生成器
gen = my_generator()
# 正常执行
print(next(gen)) # 输出:1
print(next(gen)) # 输出:2
# 关闭生成器
gen.close() # 输出:生成器已关闭
# 再次调用会抛出 StopIteration
# print(next(gen)) # StopIteration迭代器与生成器的应用场景
迭代器和生成器在以下场景中特别有用:
- 处理大量数据:当数据量很大时,使用迭代器或生成器可以节省内存。
- 惰性计算:当只需要按需处理数据时,使用迭代器或生成器可以提高效率。
- 无限序列:当需要处理无限序列时,只能使用生成器。
- 管道处理:当需要对数据进行多步处理时,使用生成器可以构建数据处理管道。
处理大量数据
示例:
python
# 处理大量数据
# 列表推导式(占用大量内存)
print("使用列表推导式:")
import sys
large_list = [i**2 for i in range(1000000)]
print(f"列表大小:{sys.getsizeof(large_list)} 字节")
del large_list # 释放内存
# 生成器表达式(占用很少内存)
print("\n使用生成器表达式:")
large_generator = (i**2 for i in range(1000000))
print(f"生成器大小:{sys.getsizeof(large_generator)} 字节")
# 按需处理
print("\n按需处理数据:")
for i, num in enumerate(large_generator):
if i < 5:
print(num, end=" ") # 输出:0 1 4 9 16
else:
break
print()惰性计算
示例:
python
# 惰性计算
# 生成器函数
print("使用生成器函数进行惰性计算:")
def process_data(data):
for item in data:
# 模拟复杂的处理
result = item * 2
yield result
# 创建数据
my_data = [1, 2, 3, 4, 5]
# 创建生成器
processor = process_data(my_data)
print("生成器已创建,尚未处理数据")
# 按需处理
print("\n按需处理数据:")
print(next(processor)) # 输出:2(处理第一个元素)
print(next(processor)) # 输出:4(处理第二个元素)
print(next(processor)) # 输出:6(处理第三个元素)无限序列
示例:
python
# 无限序列
# 生成器函数
print("使用生成器函数创建无限序列:")
def infinite_fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# 创建生成器
fib = infinite_fibonacci()
# 按需获取元素
print("\n获取前 10 个斐波那契数:")
for i in range(10):
print(next(fib), end=" ") # 输出:0 1 1 2 3 5 8 13 21 34
print()管道处理
示例:
python
# 管道处理
# 生成器函数
print("使用生成器函数构建数据处理管道:")
def read_data():
"""读取数据"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for item in data:
yield item
def filter_data(data):
"""过滤数据"""
for item in data:
if item % 2 == 0:
yield item
def process_data(data):
"""处理数据"""
for item in data:
yield item * 2
def write_data(data):
"""写入数据"""
result = []
for item in data:
result.append(item)
return result
# 构建管道
pipeline = write_data(process_data(filter_data(read_data())))
# 执行管道
print("处理结果:")
print(pipeline) # 输出:[4, 8, 12, 16, 20]总结
本章节介绍了 Python 中的迭代器和生成器:
- 迭代器:实现了
__iter__()和__next__()方法的对象,用于逐个返回元素。 - 生成器:一种特殊的迭代器,使用
yield语句来返回元素,更加简洁、高效。 - 生成器表达式:与列表推导式类似,但使用圆括号,返回生成器对象。
- 生成器函数:包含
yield语句的函数,调用时返回生成器对象。 - 生成器的高级特性:包括
send()、throw()和close()方法。 - 应用场景:处理大量数据、惰性计算、无限序列、管道处理等。
掌握迭代器和生成器的使用对于编写高效的 Python 代码非常重要。