Python高级特性:生成器完全指南

张开发
2026/4/9 16:42:30 15 分钟阅读

分享文章

Python高级特性:生成器完全指南
Python高级特性生成器完全指南按需生成内存友好前言生成器(Generator)是Python中一种特殊的迭代器它允许你按需生成值而不是一次性生成所有值并存储在内存中。这在处理大数据集或无限序列时特别有用。本文将系统讲解生成器的概念、两种创建方式、高级特性、实际应用以及性能考量帮助你掌握这一Python核心特性。一、什么是生成器1.1 生成器的核心特点特点说明惰性求值按需生成值不预先计算节省内存不需要存储所有元素保持状态可以暂停和恢复执行一次性使用只能迭代一次语法简洁类似函数使用yield1.2 生成器 vs 普通列表# 普通列表一次性生成所有元素占用大量内存 squares_list [x**2 for x in range(1000000)] print(f列表内存: {squares_list.__sizeof__()} bytes) # ~8MB # 生成器按需生成元素几乎不占内存 squares_gen (x**2 for x in range(1000000)) print(f生成器内存: {squares_gen.__sizeof__()} bytes) # ~104 bytes # 生成器只在实际迭代时才计算值 for square in squares_gen: if square 100: break print(square, end ) # 0 1 4 9 16 25 36 49 64 81 100核心优势对于大数据集生成器可以节省数百万倍的内存二、创建生成器的两种方法2.1 生成器表达式生成器表达式与列表推导式类似但使用**圆括号()**而不是方括号[]# 列表推导式 - 立即生成所有元素 list_comp [x**2 for x in range(10)] print(f列表推导式类型: {type(list_comp)}) # class list # 生成器表达式 - 按需生成元素 gen_exp (x**2 for x in range(10)) print(f生成器表达式类型: {type(gen_exp)}) # class generator # 使用生成器 for num in gen_exp: print(num, end ) # 0 1 4 9 16 25 36 49 64 81适用场景简单的转换和过滤操作。2.2 生成器函数使用yield关键字定义的函数就是生成器函数def count_up_to(max): 计数生成器生成1到max的数字 count 1 while count max: yield count # 暂停并返回值 count 1 # 创建生成器对象 counter count_up_to(5) print(type(counter)) # class generator # 使用for循环迭代 for num in count_up_to(5): print(num, end ) # 1 2 3 4 5关键特性生成器函数在每次调用next()时执行到下一个yield语句然后暂停保持所有局部变量的状态下次调用时从暂停处继续执行三、生成器的使用3.1 使用for循环迭代推荐def count_down(n): while n 0: yield n n - 1 # 使用for循环自动处理StopIteration for num in count_down(5): print(num, end ) # 5 4 3 2 13.2 手动控制使用next()gen count_up_to(3) print(next(gen)) # 输出: 1 print(next(gen)) # 输出: 2 print(next(gen)) # 输出: 3 print(next(gen)) # 抛出StopIteration异常 # 安全的手动迭代 gen count_up_to(3) while True: try: value next(gen) print(value) except StopIteration: break四、生成器的高级特性4.1 生成器状态生成器保持其执行状态包括局部变量和指令指针def stateful_gen(): print(开始执行) yield 1 print(继续执行) yield 2 print(结束执行) gen stateful_gen() print(next(gen)) # 输出开始执行返回1 print(next(gen)) # 输出继续执行返回2 print(next(gen)) # 输出结束执行抛出StopIteration输出开始执行 1 继续执行 2 结束执行 Traceback (most recent call last): ... StopIteration4.2 生成器返回值Python 3.3生成器可以使用return返回值该值会在StopIteration异常中携带def gen_with_return(): yield 1 yield 2 return 完成 gen gen_with_return() try: while True: print(next(gen)) except StopIteration as e: print(f返回值: {e.value}) # 输出: 返回值: 完成4.3 生成器委托yield fromPython 3.3使用yield from可以委托给另一个生成器或可迭代对象def chain_generators(*iterables): 将多个可迭代对象串联起来 for it in iterables: yield from it # 委托给子迭代器 # 示例串联列表、元组、字符串 gen chain_generators([1, 2], (3, 4), ab) result list(gen) print(result) # [1, 2, 3, 4, a, b] # 等价于 def manual_chain(*iterables): for it in iterables: for item in it: yield item4.4 生成器与协程.send()方法生成器也可以用于协程编程通过.send()方法可以向生成器发送值def coroutine(): print(启动协程) while True: value yield # 接收发送的值 print(f接收到值: {value}) co coroutine() next(co) # 启动协程必须先调用next或send(None) co.send(10) # 输出: 接收到值: 10 co.send(20) # 输出: 接收到值: 20 # 带返回值的协程 def calculator(): total 0 while True: value yield total if value is None: break total value return total calc calculator() next(calc) # 启动 print(calc.send(10)) # 输出: 10 print(calc.send(20)) # 输出: 30 print(calc.send(30)) # 输出: 60五、实际应用示例5.1 斐波那契数列生成器def fibonacci(): 无限斐波那契数列生成器 a, b 0, 1 while True: yield a a, b b, a b # 获取前10个斐波那契数 fib fibonacci() fib_10 [next(fib) for _ in range(10)] print(fib_10) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] # 获取小于100的所有斐波那契数 fib fibonacci() fib_under_100 [] for num in fib: if num 100: break fib_under_100.append(num) print(fib_under_100) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]5.2 读取大文件内存友好def read_large_file(file_path): 逐行读取大文件不占用过多内存 with open(file_path, r, encodingutf-8) as file: for line in file: yield line.strip() # 去除换行符 # 逐行处理大文件如10GB的日志文件 def process_line(line): 处理每一行示例函数 if ERROR in line: print(f发现错误: {line[:50]}...) # 使用生成器处理内存占用恒定 for line in read_large_file(huge_log_file.txt): process_line(line)5.3 无限序列生成器def natural_numbers(start1): 生成自然数序列无限 n start while True: yield n n 1 def even_numbers(): 生成偶数序列无限 n 0 while True: yield n n 2 def prime_numbers(): 生成素数序列无限 def is_prime(n): if n 2: return False for i in range(2, int(n**0.5) 1): if n % i 0: return False return True n 2 while True: if is_prime(n): yield n n 1 # 使用无限序列 primes prime_numbers() first_10_primes [next(primes) for _ in range(10)] print(first_10_primes) # [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]5.4 数据处理管道def read_lines(file_path): 读取文件行 with open(file_path, r) as f: for line in f: yield line.strip() def filter_lines(lines, keyword): 过滤包含关键字的行 for line in lines: if keyword in line: yield line def convert_to_uppercase(lines): 转换为大写 for line in lines: yield line.upper() def write_lines(lines, output_path): 写入文件 with open(output_path, w) as f: for line in lines: f.write(line \n) # 构建处理管道 input_file data.txt output_file output.txt keyword ERROR # 管道读取 - 过滤 - 转换 - 写入 lines read_lines(input_file) filtered filter_lines(lines, keyword) uppercased convert_to_uppercase(filtered) write_lines(uppercased, output_file) print(f处理完成结果保存到 {output_file})六、练习题杨辉三角生成器def triangles(): 杨辉三角生成器逐行生成 row [1] while True: yield row # 计算下一行 row [1] [row[i] row[i1] for i in range(len(row)-1)] [1] # 测试生成前10行杨辉三角 results [] n 0 for t in triangles(): results.append(t) n 1 if n 10: break # 打印杨辉三角 for i, row in enumerate(results, 1): # 格式化输出使三角形居中显示 print(f第{i:2d}行: {row}) # 输出示例 # 第 1行: [1] # 第 2行: [1, 1] # 第 3行: [1, 2, 1] # 第 4行: [1, 3, 3, 1] # 第 5行: [1, 4, 6, 4, 1] # ...七、性能考虑7.1 内存效率对比数据结构内存占用适用场景列表高所有元素小数据集、需要随机访问生成器极低恒定大数据集、流式处理元组中等不可变数据7.2 速度对比import timeit # 列表推导式 def test_list(): return [x**2 for x in range(10000)] # 生成器表达式 def test_generator(): return (x**2 for x in range(10000)) # 求和性能测试 list_time timeit.timeit(sum([x**2 for x in range(10000)]), number1000) gen_time timeit.timeit(sum((x**2 for x in range(10000))), number1000) print(f列表求和: {list_time:.4f}秒) print(f生成器求和: {gen_time:.4f}秒) # 生成器通常略慢约10-20%但内存占用小得多7.3 一次性使用特性# 生成器只能迭代一次 gen (x**2 for x in range(5)) print(list(gen)) # [0, 1, 4, 9, 16] print(list(gen)) # [] - 已经耗尽 # 需要多次使用可以转换为列表或重新创建 values list((x**2 for x in range(5))) # 转换为列表 print(values) # [0, 1, 4, 9, 16] print(values) # [0, 1, 4, 9, 16] - 可以多次使用八、总结知识点要点定义按需生成值的迭代器创建方式1生成器表达式(expr for item in iterable)创建方式2生成器函数使用yield关键字核心优势节省内存、支持无限序列限制一次性使用、速度略慢高级特性yield from委托、.send()协程、返回值适用场景大数据集、流式处理、无限序列、管道处理

更多文章