列表推导式和生成器表达式真的能让代码“ 更易于理解 ” 吗?
1. 列表推导式(List Comprehensions)
- 语法:用方括号
[]
包裹。 - 特点:立即计算并生成完整列表,所有元素一次性存储在内存中。
- 适用场景:
- 需要多次访问或修改数据。
- 需要索引、切片等列表操作。
- 数据量较小,内存充足。
示例
# 生成0-9的列表
lst = [x for x in range(10)]
# 带条件的推导式(仅偶数)
even_lst = [x for x in range(10) if x % 2 == 0]
# 多层循环(笛卡尔积)
pairs = [(x, y) for x in range(3) for y in range(2)]
对比以下写法:
lst=[]
for x in range(10):
lst.append(x)
even_lst=[]
for x in range(10):
if x%2==0:
even_lst.append(x)
pairs=[]
for x in range(3):
for y in range(2):
pairs.append((x,y))
2.生成器表达式(Generator Expressions)
- 语法:用圆括号
()
包裹。 - 特点:惰性计算,按需逐个生成元素,不占用全部内存。
- 适用场景:
- 处理大规模数据(如文件、流数据)。
- 只需单次遍历。
- 内存敏感的场景(避免一次性加载所有数据)。
示例
# 生成0-9的生成器
gen = (x for x in range(10))
# 带条件的生成器
even_gen = (x for x in range(10) if x % 2 == 0)
# 生成器作为函数参数(无需额外括号)
total = sum(x * x for x in range(10))
3.核心区别
特性 | 列表推导式 | 生成器表达式 |
---|---|---|
内存占用 | 高(存储所有元素) | 低(逐个生成) |
计算时机 | 立即执行 | 惰性计算(按需生成) |
可重用性 | 可多次遍历 | 仅能遍历一次 |
语法符号 | 方括号 [] | 圆括号 () |
适用场景 | 小数据、多次操作或需要索引 | 大数据、单次遍历或内存敏感场景 |
4. 高级用法
(1) 条件过滤
# 列表推导式
filtered_list = [x for x in range(100) if x % 3 == 0]
# 生成器表达式
filtered_gen = (x for x in range(100) if x % 3 == 0)
(2) 多层循环
# 列表推导式(生成笛卡尔积)
matrix = [[(i, j) for j in range(3)] for i in range(2)]
# 生成器表达式
gen = ((i, j) for i in range(2) for j in range(3))
(3) 函数组合
# 使用生成器表达式转换数据
squared = (x**2 for x in some_generator)
# 转换为列表(等价于列表推导式)
lst = list(squared)
5. 注意事项
- 生成器只能遍历一次:遍历后生成器会耗尽,需重新创建。
- 副作用操作:避免在生成器中执行打印、修改外部变量等操作(惰性计算可能导致意外结果)。
- 数据源变动:生成器依赖原始数据源,若数据源被修改,结果可能变化。
- 用列表推导式:当需要快速生成列表且数据量小,或需要多次操作。
- 用生成器表达式:处理大规模数据、节省内存,或作为函数参数(如
sum()
、max()
)。