📄 一句话概括
partial 固定一个参数、pipe 把多个函数串起来,两种都不写新函数体(0 行);组合的意思是拿现成的小东西拼,而不是为每种拼法造新函数。
📝 本节和前面几节的关系
A.5 说函数是值,这一节说能当值就能拼。
一、实测:两种组合
固定参数(partial):add5 = partial(add, 5),新函数体 0 行。
串成管道(pipe):pipe(f, g, h)(3) 依次跑三步,新函数体 0 行。
手写对照版:固定参数要写 1 行函数体,手写管道要写 3 个函数。
两版结果完全一致(8 与 8、49 与 49)。
二、组合省的是什么
省的不是行数,是【不新增概念】。 每造一个新函数,就多一个名字要记、多一个地方要维护。 组合只声明【怎么拼】,拼出来的东西可以不留名字(就地传出去)。
三、代价:调试变难
栈里全是匿名函数,出错时得一层层拆开看。 所以组合适合【步骤短、每步都很纯】的场合。 步骤一长就该拆回来命名——命名不是落后,是给人看的。
四、动手 Demo:特征4:可以灵活组合函数和参数
用 partial 固定一个参数,用 pipe 串三步。 各写一版手写对照,比函数体行数。
import functools
def add(a, b):
return a + b
def add5_manual(x):
return add(5, x)
add5 = functools.partial(add, 5)
def pipe(*fns):
def run(x):
for f in fns:
x = f(x)
return x
return run
steps = pipe(lambda n: n * 2, lambda n: n + 1, lambda n: n * n)
print(add5(3), add5_manual(3)) # 8 8
print(steps(3), (3 * 2 + 1) ** 2) # 49 49
实跑输出:
--------------------------------------------------------------------
特征4:可以灵活组合函数和参数
--------------------------------------------------------------------
固定一个参数、串起多个函数,**这两种组合各能省多少行:**
做法 写法 要新写的函数体 结果
--------------------------------------------------------------------
手写固定参数 add5_manual(x) 1 8
partial add5 = partial(add, 5) 0 8
手写管道 三步各写一次 3 49
pipe 组合 pipe(f, g, h) 0 49
两种等价写法结果一致 True
组合出来的新函数 0 行新函数体
可组合的基本动作 2 种(固定参数/串成管道)
**注意第 4 行:`steps(3)` 走了三步(×2、+1、平方),**一行新函数都没写。**
**这就是组合的意思:**拿现成的小东西拼,而不是为每种拼法造一个新函数。
**代价是调试**:出错时得一层层拆开看,**栈里全是匿名函数。**
实测:partial 与 pipe 都不写新函数体(0 行),结果和手写版完全一致。 组合省的不是行数,是不新增概念——每造一个函数就多一个名字要管。 代价是调试难:栈里全是匿名函数,步骤一长就该拆回来命名。
30 秒实验
- 把你代码里三个连续的清洗步骤(去空、转小写、去重)串成一条 pipe。
- 再判断:这条 pipe 出错时,你能一眼看出是哪一步的问题吗?
常见误区
- 以为组合一定比命名清楚。组合一长,读的人就迷路了。
- 为了组合而组合,把两行的逻辑拆成五个 lambda。那是自找麻烦。
自测三问(点开对答案)
1. 两种组合方式是什么? —— 固定一个参数(partial)和串成管道(pipe)。 2. 组合省的是什么? —— 不新增概念、不多一个要维护的名字,而不是省行数。 3. 组合的代价? —— 调试变难,栈里全是匿名函数。- ☐ A.7 特征5:没有副作用
相关笔记
- 特征3:将函数作为值进行处理 — 上一条
- 特征5:没有副作用 — 分水岭之一
- 提高构件独立性的诀窍 — 独立性的另一条路
- 🧩 面向对象是怎样工作的 · 索引