惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
月光博客
月光博客
D
DataBreaches.Net
云风的 BLOG
云风的 BLOG
F
Fortinet All Blogs
T
The Blog of Author Tim Ferriss
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
aimingoo的专栏
aimingoo的专栏
U
Unit 42
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
MyScale Blog
MyScale Blog
T
Tailwind CSS Blog
N
Netflix TechBlog - Medium
B
Blog
博客园_首页
G
Google Developers Blog
Recent Announcements
Recent Announcements
博客园 - 【当耐特】
P
Proofpoint News Feed
博客园 - 司徒正美
Hugging Face - Blog
Hugging Face - Blog
MongoDB | Blog
MongoDB | Blog
Last Week in AI
Last Week in AI

博客园 - 箫笛

Tkinter - Entry 输入框组件 Tkinter - Button 组件 Tkinter - Label 组件 Tkinter - tk 变量 Tkinter - 事件与绑定 Tkinter - 几何管理器 Tkinter - 核心概念 Tkinter - 快速开始 Tkinter - 介绍 Python 编程 - 条件表达式 Python 编程 - 星号下划线参数释义 shell 编程 - shell 脚本的交互方式 Python insall - macOS 系统安装python的几种方式 Miniconda - Python 环境管理工具 Tkinter - Python GUI 开发 Python 编程 - 下划线命名的区别 Python 编程 - 元类编程 Python 编程 - 多重继承与MRO Python 编程 - 描述符协议 Python 编程 - 类型注解 Python 编程 - 集合 Python 编程 - 装饰器 Python 编程 - 闭包 Python 编程 - 列表推导式 Python 编程 - 函数式编程 Python 编程 - lambda 函数 Python 编程 - 文件操作 Python 编程 - 输入与输出 Python 编程 - 面向对象编程 Python 编程 - 元组(tuple)
Python 编程 - 生成器表达式
箫笛 · 2026-06-25 · via 博客园 - 箫笛

生成器表达式(Generator Expression) 是 Python 3 中一种内存效率极高的迭代器创建方式。它外观类似列表推导式,但使用圆括号 (),核心区别在于惰性求值(Lazy Evaluation)——边迭代边生成值,不会一次性将所有数据加载到内存。

1. 基本语法

(expression for item in iterable if condition)

对比列表推导式:

# 列表推导式(立即生成所有数据,占用内存)
list_comp = [x**2 for x in range(1000)]  # 占用 ~8KB 以上

# 生成器表达式(惰性生成,只记录算法)
gen_exp = (x**2 for x in range(1000))    # 占用 ~几百字节

2. 核心特性与使用

生成器表达式返回一个 生成器对象,它既是迭代器也是可迭代对象。

基础遍历:

gen = (i * 2 for i in range(5))
for val in gen:
    print(val, end=" ")  # 输出: 0 2 4 6 8

手动获取值(使用 next()):

gen = (i for i in range(3))
print(next(gen))  # 0
print(next(gen))  # 1
print(next(gen))  # 2
# print(next(gen))  # 抛出 StopIteration 异常

3. 高级应用与最佳实践

(1) 函数调用中省略多余括号

当生成器表达式作为唯一参数传入函数时,可以省略外层的圆括号,写法更简洁:

# 计算 1 到 1亿 的平方和(内存占用极低)
sum_of_squares = sum(x*x for x in range(100_000_000))
# 而不是 sum((x*x for x in range(...))) 

(2) 构建数据管道(流式处理)

生成器可以串联,处理超大文件或无限序列:

# 处理超大日志文件,筛选含 'ERROR' 的行,并提取时间戳
lines = (line for line in open('huge_log.txt'))          # 流式读行
errors = (line for line in lines if 'ERROR' in line)     # 惰性筛选
timestamps = (line.split()[0] for line in errors)        # 惰性提取

for ts in timestamps:  # 逐条处理,内存只存当前行
    print(ts)

(3) 嵌套循环与笛卡尔积

# 生成坐标对 (0,0) (0,1) ... (2,3)
coords = ((x, y) for x in range(3) for y in range(4))

4. 关键陷阱与注意事项(务必留意)

特性 说明 示例
一次性消费 生成器只能遍历一次。遍历完后内部指针耗尽,再次遍历为空。 gen = (x for x in [1,2,3]); list(gen) # [1,2,3]; list(gen) # []
不存储索引 无法像列表那样通过下标 gen[0] 访问,也不支持 len() 只能顺序迭代。
延迟计算的副作用 如果依赖外部变量,变量值在迭代时才被读取,而非定义时。 i = 5; gen = (x+i for x in range(3)); i = 10; list(gen) # 输出 [10,11,12]
性能取舍 内存占用极低,但每次取值有计算开销。重复遍历多次时,列表推导式更快。 数据量小(< 1000)用列表;数据量大或无限流用生成器。

5. 生成器表达式 vs yield 函数

  • 生成器表达式:适合简单逻辑的单行惰性计算(如 (x*2 for x in seq))。
  • yield 生成器函数:适合复杂逻辑(含循环嵌套、分支判断、状态保持)。
# 等价表达
gen1 = (x**2 for x in range(3))

def gen2():
    for x in range(3):
        yield x**2

6. 总结速查

  • 语法( 结果 for 变量 in 可迭代对象 [if 条件] )
  • 核心优势:处理海量数据、流式IO时,内存占用极小。
  • 黄金法则:如果你只需要迭代一次,且数据量巨大,请使用生成器表达式;如果需要反复使用或随机访问,请使用列表推导式。