【python】生成器
文章目录
- 创建生成器的两种方式
- 1. 生成器函数
- 2. 生成器表达式
- 生成器的特点
- 惰性求值
- 状态保持
- 生成器的优势
- 1. 内存效率
- 2. 无限序列
- 生命周期
- 执行状态
- 内存管理
- 应用场景
- 1. 处理大型数据集
- 2. 数据管道
- 3. 协程和状态机
- 4. 分页处理
- 高级特性
- 1. 生成器委托
- 2. 上下文管理器
- 总结
生成器是Python中一种特殊的迭代器,它允许你按需生成值,而不是一次性生成所有值并存储在内存中。生成器使用
yield语句而不是
return来返回值。
创建生成器的两种方式
1. 生成器函数
使用yield语句的函数
def simple_generator():yield 1yield 2yield 3# 使用生成器
gen = simple_generator()
print(next(gen)) # 输出: 1
print(next(gen)) # 输出: 2
print(next(gen)) # 输出: 3
2. 生成器表达式
类似于列表推导式,但使用圆括号
# 生成器表达式
squares = (x*x for x in range(5))print(next(squares)) # 输出: 0
print(next(squares)) # 输出: 1
print(next(squares)) # 输出: 4
生成器的特点
惰性求值
def count_up_to(n):count = 1while count <= n:yield countcount += 1# 不会立即执行,只有在迭代时才会生成值
counter = count_up_to(5)
for num in counter:print(num) # 输出: 1, 2, 3, 4, 5
状态保持
def fibonacci():a, b = 0, 1while True:yield aa, b = b, a + bfib = fibonacci()
for i in range(10):print(next(fib)) # 输出斐波那契数列的前10个数字
生成器的优势
1. 内存效率
# 传统方式 - 占用大量内存
def read_large_file_traditional(filename):with open(filename, 'r') as file:return file.readlines() # 一次性读取所有行到内存# 生成器方式 - 内存友好
def read_large_file_generator(filename):with open(filename, 'r') as file:for line in file:yield line.strip()# 使用生成器逐行处理大文件
for line in read_large_file_generator('large_file.txt'):process_line(line) # 每次只处理一行,不占用大量内存
2. 无限序列
def infinite_sequence():num = 0while True:yield numnum += 1# 可以表示无限序列而不耗尽内存
inf_seq = infinite_sequence()
for i in range(100):print(next(inf_seq))
生命周期
执行状态
内存管理
应用场景
1. 处理大型数据集
def process_large_dataset(data_generator, batch_size=1000):batch = []for item in data_generator:batch.append(process_item(item))if len(batch) >= batch_size:yield batchbatch = []if batch:yield batch# 分批处理数据,避免内存溢出
for batch in process_large_dataset(data_generator()):save_to_database(batch)
2. 数据管道
def read_sensor_data():"""模拟读取传感器数据"""import randomwhile True:yield random.randint(0, 100)def filter_data(data_stream, threshold=50):"""过滤数据"""for data in data_stream:if data > threshold:yield datadef aggregate_data(filtered_stream, window_size=10):"""聚合数据"""window = []for data in filtered_stream:window.append(data)if len(window) >= window_size:yield sum(window) / len(window)window = []# 构建数据处理管道
sensor_data = read_sensor_data()
filtered_data = filter_data(sensor_data)
aggregated_data = aggregate_data(filtered_data)for result in aggregated_data:print(f"平均值: {result}")
3. 协程和状态机
def state_machine():state = "START"while True:if state == "START":data = yield "开始处理"state = "PROCESSING"elif state == "PROCESSING":data = yield f"处理数据: {data}"if data == "complete":state = "COMPLETE"elif state == "COMPLETE":yield "处理完成"breaksm = state_machine()
next(sm) # 启动生成器
print(sm.send("data1")) # 输出: 处理数据: data1
print(sm.send("complete")) # 输出: 处理完成
4. 分页处理
def paginate_api(endpoint, page_size=100):page = 1while True:# 模拟API调用data = fetch_data_from_api(endpoint, page, page_size)if not data:breakfor item in data:yield itempage += 1# 使用生成器透明地处理分页
for item in paginate_api("users"):process_user(item)
高级特性
1. 生成器委托
def chain_generators(*generators):for gen in generators:yield from gengen1 = (x for x in range(3))
gen2 = (x for x in range(3, 6))
chained = chain_generators(gen1, gen2)for item in chained:print(item) # 输出: 0, 1, 2, 3, 4, 5
2. 上下文管理器
from contextlib import contextmanager@contextmanager
def timer():import timestart = time.time()yieldend = time.time()print(f"执行时间: {end - start:.2f}秒")# 使用生成器作为上下文管理器
with timer():# 执行一些耗时操作sum(i for i in range(1000000))
总结
- 使用生成器表达式代替列表推导式来处理大数据集
- **使用
yield from**来委托子生成器 - 及时关闭不再使用的生成器
- **避免在生成器中使用
return**返回值(Python 3.3+支持)
# 好的实践
def efficient_processing(data):return (transform(item) for item in data if condition(item))# 不好的实践
def inefficient_processing(data):result = []for item in data:if condition(item):result.append(transform(item))return result
生成器是Python中处理流式数据和内存敏感任务的强大工具,合理使用可以显著提升程序性能和可维护性。
