核心篇 · Core
lv.1 入门
kp-011
推导式(comprehensions)
1. 一句话定义
推导式是"由一个可迭代对象构造新容器"的声明式语法:[表达式 for 变量 in 可迭代 if 条件],覆盖 list/dict/set 三种形式与生成器表达式。
2. 为什么重要
它是 Pythonic 的第一标志:同一意图(过滤+映射)比等价 for 循环短一半且无临时变量;同时是通向生成器表达式(惰性)与 asyncio 数据流的自然入口。
3. 前置知识
kp-006(for 循环)、kp-009/kp-010(容器)。
4. 核心概念
python
squares = [x * x for x in range(10)] # 列表
evens = [x for x in range(10) if x % 2 == 0] # 带过滤
pairs = {k: v for k, v in [("a",1),("b",2)]} # 字典
uniq = {c for c in "abracadabra"} # 集合
lazy = (x * x for x in range(10)) # 生成器表达式(惰性)- 条件位置两处不同:
for x in it if cond是过滤;[a if cond else b for x in it]是三目变换。 - 嵌套:从左到右读即外层到内层循环。
5. 原理与机制
等价展开规则:推导式 = "创建空容器 + for 循环填充"的编译糖(有自己的局部作用域,循环变量不泄漏)。
python
[x * 2 for x in xs if p(x)]
# ≈
out = []
for x in xs:
if p(x):
out.append(x * 2)生成器表达式不立即求值,sum(x*x for x in big) 边算边耗,不构造中间列表——大数据下的关键差异。
6. 关键事实(模型/图示)
text
读法口诀:for 在前(数据从哪来),if 在后(留下谁),表达式最前(变成什么)
[expr for x in A for y in B if c] ≡ for x in A: for y in B: if c: yield expr7. 直观类比
for 循环是流水线上的工人一件件搬;推导式是开模:把"什么样的件、怎么变"描述成图纸,机器一次成型。图纸复杂到没人看得懂时,就该回去用流水线。
8. 实例与案例
python
# 过滤 + 排序组合:取出分数及格者的姓名并按分数倒序
names = sorted(
(n for n, s in scores.items() if s >= 60),
key=lambda n: -scores[n],
)
# 扁平化二维列表
flat = [x for row in matrix for x in row]9. 常见误区
- 套超过两层 ——
[... for x in A for y in B for z in C ...]可读性崩坏,改普通循环。 - 生成器表达式当列表用第二次 —— 耗尽后为空;需要多次用列表推导式或重建。
- 在推导式里做副作用(写文件、print) —— 语义陷阱,用普通 for 表达意图。
- 以为推导式更快是"银弹" —— 常量级优势,大逻辑差异来自是否惰性,不是语法本身。
10. 自测题
[x for x in range(10) if x % 2]输出什么?sum(len(w) for w in words)与sum([len(w) for w in words])的差异?{x: x**2 for x in range(3)}是什么?
参考答案
[1, 3, 5, 7, 9](奇数)。- 前者生成器表达式,逐个计算不建中间列表;后者先建完整列表再求和。
- 字典推导式,得
{0: 0, 1: 1, 2: 4}。
11. 与其他知识点的关系
12. 延伸阅读
- Python 官方教程 §5.1.3 List Comprehensions