Python 第十节 迭代器与生成器使用详解及区别
·
一、 迭代器 (Iterator)
基本概念
迭代器是一个可以记住遍历位置的对象,实现了迭代器协议(__iter__() 和 __next__() 方法)。
创建自定义迭代器
class MyIterator:
def __init__(self, max_value):
self.max_value = max_value
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current < self.max_value:
self.current += 1
return self.current - 1
else:
raise StopIteration
# 使用自定义迭代器
my_iter = MyIterator(5)
for num in my_iter:
print(num) # 输出: 0, 1, 2, 3, 4
内置迭代器使用 iter()
# 列表迭代器
my_list = [1, 2, 3]
list_iter = iter(my_list)
print(next(list_iter)) # 1
print(next(list_iter)) # 2
print(next(list_iter)) # 3
# 字典迭代器
my_dict = {'a': 1, 'b': 2}
dict_iter = iter(my_dict.items())
for key, value in dict_iter:
print(f"{key}: {value}")
二、 生成器 (Generator)
生成器函数
使用 yield 关键字创建生成器函数。
def my_generator(max_value):
current = 0
while current < max_value:
yield current
current += 1
# 使用生成器
gen = my_generator(5)
for num in gen:
print(num) # 输出: 0, 1, 2, 3, 4
生成器表达式
类似列表推导式,但使用圆括号。
# 生成器表达式
squares_gen = (x**2 for x in range(5))
for square in squares_gen:
print(square) # 输出: 0, 1, 4, 9, 16
# 与列表推导式的区别
squares_list = [x**2 for x in range(5)] # 立即计算所有值
高级生成器用法
def fibonacci_generator(limit):
a, b = 0, 1
count = 0
while count < limit:
yield a
a, b = b, a + b
count += 1
# 生成斐波那契数列
fib_gen = fibonacci_generator(10)
for num in fib_gen:
print(num)
三、 主要区别

四、 注意事项
迭代器注意事项
# 1. 迭代器只能遍历一次
my_list = [1, 2, 3]
my_iter = iter(my_list)
print(list(my_iter)) # [1, 2, 3]
print(list(my_iter)) # [] - 空列表,因为迭代器已耗尽
# 2. 手动处理 StopIteration
my_iter = iter([1, 2, 3])
try:
while True:
item = next(my_iter)
print(item)
except StopIteration:
print("迭代结束")
生成器注意事项
# 1. 生成器表达式只能使用一次
squares = (x**2 for x in range(3))
print(sum(squares)) # 5 (0+1+4)
print(sum(squares)) # 0 - 生成器已耗尽
# 2. yield 的返回值
def generator_with_send():
received = yield "开始"
yield f"收到: {received}"
gen = generator_with_send()
print(next(gen)) # "开始"
print(gen.send("Hello")) # "收到: Hello"
# 3. 生成器关闭
def infinite_generator():
i = 0
try:
while True:
yield i
i += 1
except GeneratorExit:
print("生成器被关闭")
gen = infinite_generator()
print(next(gen)) # 0
gen.close() # 输出: "生成器被关闭"
五、 实用技巧
管道式处理
def read_lines(filename):
with open(filename, 'r') as file:
for line in file:
yield line.strip()
def filter_comments(lines):
for line in lines:
if not line.startswith('#'):
yield line
def make_uppercase(lines):
for line in lines:
yield line.upper()
# 组合生成器管道
lines = read_lines('example.txt')
filtered = filter_comments(lines)
uppercased = make_uppercase(filtered)
for line in uppercased:
print(line)
惰性求值
def process_data(data):
# 模拟耗时操作
print("处理数据...")
return data * 2
def lazy_processor(data_list):
for data in data_list:
yield process_data(data)
# 只有在需要时才处理数据
data = [1, 2, 3, 4, 5]
lazy_gen = lazy_processor(data)
# 只处理前3个元素
for i, result in enumerate(lazy_gen):
if i >= 3:
break
print(result)
六、 性能比较
import time
import sys
# 内存使用比较
def memory_usage():
list_comp = [x**2 for x in range(1000000)]
gen_expr = (x**2 for x in range(1000000))
print(f"列表推导式内存: {sys.getsizeof(list_comp)} 字节")
print(f"生成器表达式内存: {sys.getsizeof(gen_expr)} 字节")
# 执行时间比较
def timing_comparison():
# 列表推导式(立即执行)
start = time.time()
result1 = sum([x**2 for x in range(1000000)])
time1 = time.time() - start
# 生成器表达式(惰性执行)
start = time.time()
result2 = sum((x**2 for x in range(1000000)))
time2 = time.time() - start
print(f"列表推导式时间: {time1:.4f}秒")
print(f"生成器表达式时间: {time2:.4f}秒")
memory_usage()
timing_comparison()
总结
- 迭代器适用于需要复杂状态管理的场景
- 生成器更适用于简单的序列生成,代码更简洁
- 两者都支持惰性求值,节省内存
- 生成器
只能遍历一次,迭代器根据实现可能支持多次遍历 - 在处理大数据集时,生成器通常更高效
根据具体需求选择合适的工具,在大多数序列处理场景中,生成器是更优的选择。
更多推荐
所有评论(0)