Python3 入门教程
推导式与生成器表达式
本教程共 70 篇 · 第 20 篇 · 更新于 2026-07-22 · 约 2 分钟阅读
PythonPython3 入门教程列表推导式字典推导式生成器表达式惰性求值
20. 推导式与生成器表达式
本节目标:掌握列表、字典、集合推导式和生成器表达式,用简洁的语法高效创建数据结构。
列表推导式
列表推导式是把一个循环压缩成一行的语法糖:
# 传统写法
squares = []
for x in range(10):
squares.append(x ** 2)
# 推导式写法
squares = [x ** 2 for x in range(10)]
可读性不下降,代码更紧凑。
带条件的列表推导式
# 只保留偶数的平方
evens = [x ** 2 for x in range(10) if x % 2 == 0]
# [0, 4, 16, 36, 64]
# 多重条件
result = [x for x in range(100) if x % 3 == 0 if x % 5 == 0]
# [0, 15, 30, 45, 60, 75, 90]
多层循环的推导式
>>> [(x, y) for x in [1, 2] for y in ['a', 'b']]
[(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
等价于:
result = []
for x in [1, 2]:
for y in ['a', 'b']:
result.append((x, y))
Warning推导式嵌套超过两层就很难读了。复杂逻辑还是展开成普通循环。
带 else 的推导式
条件表达式可以放在前面:
# 奇数保留原值,偶数变为其一半
result = [x if x % 2 else x // 2 for x in range(10)]
# [0, 1, 1, 3, 2, 5, 3, 7, 4, 9]
Note这里的
if不是过滤,而是条件表达式(三元表达式),每个元素都会生成一个结果。
字典推导式
# 数字到平方的映射
>>> {x: x**2 for x in range(5)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# 从已有字典筛选
>>> prices = {"apple": 3, "banana": 2, "cherry": 8}
>>> {k: v for k, v in prices.items() if v > 2}
{'apple': 3, 'cherry': 8}
# 交换键值(值必须可哈希)
>>> {v: k for k, v in {"a": 1, "b": 2}.items()}
{1: 'a', 2: 'b'}
# 用两个列表创建字典
>>> names = ["Alice", "Bob"]
>>> ages = [25, 30]
>>> {name: age for name, age in zip(names, ages)}
{'Alice': 25, 'Bob': 30}
集合推导式
>>> {x**2 for x in range(10)}
{0, 1, 4, 81, 64, 9, 16, 49, 25, 36}
>>> {x for x in 'abracadabra' if x not in 'abc'}
{'d', 'r'}
集合推导式自动去重,适合需要唯一结果的场景。
生成器表达式
把列表推导式的方括号 [] 换成圆括号 (),就得到生成器表达式:
>>> gen = (x ** 2 for x in range(10))
>>> gen
<generator object <genexpr> at 0x...>
生成器表达式不会立即计算所有结果,而是惰性求值——你问它要一个,它算一个。
>>> next(gen)
0
>>> next(gen)
1
>>> sum(x ** 2 for x in range(10)) # 括号可以省略
285
Tip如果只是遍历一次,不需要存下所有结果,用生成器表达式比列表推导式更省内存。
# 列表推导式:创建包含 1000 万个整数的列表,可能占用几百 MB total = sum([x ** 2 for x in range(10_000_000)]) # 生成器表达式:不存列表,算一个加一个 total = sum(x ** 2 for x in range(10_000_000))
推导式 vs 生成器:怎么选
| 场景 | 推荐 |
|---|---|
| 需要反复访问、随机索引 | 列表推导式 [] |
| 只遍历一次、数据量大 | 生成器表达式 () |
| 需要键值对查找 | 字典推导式 {} |
| 需要去重 | 集合推导式 {} |
Note元组没有推导式。
(x for x in range(5))是生成器表达式,不是元组推导式。需要元组时,用tuple(x for x in range(5))把生成器转成元组。
一个实用技巧:扁平化列表
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
注意循环顺序:跟普通嵌套循环一样,外层循环写前面,内层写后面。
来源:参考了 runoob「Python 推导式」、liaoxuefeng「列表生成式」等,改写后所得。