文章
合集Python 语言基础第 9 / 21 篇

Python 生成器表达式

Summary

生成器表达式用类似列表推导式的语法创建生成器对象,惰性计算,逐个产出,不会一次性生成完整列表。

一、列表推导式 vs 生成器表达式

特性列表推导式 [...]生成器表达式 (...)
语法[x for x in iterable](x for x in iterable)
返回值list(完整列表)generator(生成器对象)
内存占用一次性存储所有元素惰性计算,逐个产出
遍历次数可多次遍历只能遍历一次(耗尽后为空)
访问方式支持索引 lst[0]不支持索引,只能迭代
# 列表推导式 —— 立即计算,占用内存
squares_list = [x**2 for x in range(1000000)]  # 内存中存100万个整数

# 生成器表达式 —— 惰性计算,几乎不占内存
squares_gen = (x**2 for x in range(1000000))   # 只是一个生成器对象

二、使用情形

  1. 迭代遍历(最常用): 迭代完后消失,阅后即焚
gen = (x**2 for x in range(5))

for val in gen:
    print(val)  # 0, 1, 4, 9, 16

# 再次遍历为空(已耗尽)
for val in gen:
    print(val)  # 无输出
  1. 用 next() 逐个获取:说明这是个迭代器
gen = (x for x in "abc")
print(next(gen))  # 'a'
print(next(gen))  # 'b'
print(next(gen))  # 'c'
print(next(gen))  # StopIteration 异常
  1. 转换为其他类型(会立即计算):强制类型转换时精度扩展
gen = (x*2 for x in range(5))

list(gen)   # [0, 2, 4, 6, 8]
tuple(gen)  # () —— 已耗尽,为空
set(gen)    # set() —— 已耗尽

三、总结

  1. 惰性求值:元素在需要时才生成,节省内存
  2. 一次性:遍历后即耗尽,不能重复使用
  3. 无索引:不支持随机访问,只能顺序迭代
  4. 括号规则:
    • 单参数函数调用时外层括号可省略:sum(x for x in range(10))
    • 多参数时必须加括号:func(a, (x for x in b), c)