Day 095 — 函数式编程深入 · 图解
1. reduce 归约过程
reduce(lambda acc, x: acc + x, [1, 2, 3, 4, 5])
步骤:
初始: acc=1
Step1: acc=1+2=3
Step2: acc=3+3=6
Step3: acc=6+4=10
Step4: acc=10+5=15
[1, 2, 3, 4, 5]
↓
[1+2, 3, 4, 5] → [3, 3, 4, 5]
↓
[3+3, 4, 5] → [6, 4, 5]
↓
[6+4, 5] → [10, 5]
↓
[10+5] → [15]
2. 柯里化 vs 偏函数
普通函数:
add(a, b, c) → result
柯里化:
add(1)(2)(3) → result
add(1)(2, 3) → result
add(1, 2)(3) → result
特点: 每次调用返回新函数,直到参数足够
偏函数 (partial):
add_1_2 = partial(add, 1, 2)
add_1_2(3) → result
特点: 固定部分参数,生成新函数
┌─────────────────────────────────────────┐
│ 柯里化 │
│ │
│ add ──► add(1) ──► add(1)(2) ──► result │
│ │ │ │
│ ▼ ▼ │
│ 新函数 新函数 │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ 偏函数 │
│ │
│ add + (1,2) ──► add_1_2 ──► add_1_2(3) │
│ │ │ │
│ ▼ ▼ │
│ 新函数 result │
└─────────────────────────────────────────┘
3. 不可变数据结构
可变 vs 不可变:
可变 list:
data = [1, 2, 3]
other = data
data.append(4)
→ data = [1, 2, 3, 4]
→ other = [1, 2, 3, 4] (一起变了!)
不可变 tuple:
data = (1, 2, 3)
other = data
data = data + (4,) # 创建新对象
→ data = (1, 2, 3, 4)
→ other = (1, 2, 3) (不变!)
不可变操作模式:
┌──────────┐ ┌──────────┐
│ 原始数据 │ │ 原始数据 │
│ [1,2,3] │ │ [1,2,3] │ ← 不变
└────┬─────┘ └──────────┘
│
▼ 操作
┌──────────┐
│ 新数据 │
│ [1,2,3,4]│ ← 新对象
└──────────┘
4. 管道模式
数据处理管道:
输入: " Hello World "
│
▼ strip
"Hello World"
│
▼ lower
"hello world"
│
▼ replace(" ", "_")
"hello___world"
│
▼ title
"Hello___World"
│
▼ 正则清理
"Hello_World"
│
▼ 输出
函数组合:
pipe_forward(f1, f2, f3)(x) = f3(f2(f1(x)))
compose(f1, f2, f3)(x) = f1(f2(f3(x)))
5. 惰性求值
惰性求值 vs 急切求值:
急切求值 (列表推导):
data = [x*2 for x in range(1000000) if x%2==0][:10]
→ 计算所有 500000 个元素,只用 10 个
→ 浪费 99.998% 的计算
惰性求值 (管道):
data = LazyRange(1000000)
.filter(x%2==0)
.map(x*2)
.take(10)
→ 只计算前 20 个元素(10个偶数 × 2)
→ 按需计算,内存友好
时间线: ──────────────────────────────►
急切: [计算全部500000个]→[取前10个]
惰性: [取1个]→[取1个]→[取1个]...→[够了,停]
6. singledispatch 类型分派
singledispatch 工作流程:
┌─────────────┐
│ 调用 serialize │
│ (value) │
└──────┬──────┘
│
▼
┌─────────────┐
│ 检查 value 类型 │
└──────┬──────┘
│
┌───────────────┼───────────────┐
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ int │ │ str │ │ list │
│ serialize │ │ serialize │ │ serialize │
│ (int) │ │ (str) │ │ (list) │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
│ │ │
▼ ▼ ▼
"int:42" "str:hello" "list:[1,2,3]"
类似 Java 的方法重载,但更灵活