函数式编程(Functional Programming,FP)是一种把"计算"看作数学函数求值的编程范式——它不像面向对象那样关注"对象状态",而是强调用函数来描述数据的变换过程。Python 并非纯函数式语言,但它对这套思想的支持相当完善,掌握它能让你的代码更简洁、更易测试、更少 bug。下面我们一层一层把这件事讲清楚。
🧭 核心思想:函数式编程在想什么?
函数式编程的哲学核心只有一句话:数据流过一系列纯函数,产生结果,过程中不改变任何外部状态。 这和流水线工厂很像——每道工序只做一件事,不污染上下游。
🔬 核心概念详解
1. 纯函数(Pure Function)
纯函数有两个铁律:相同输入永远返回相同输出,以及不产生任何副作用(不修改全局变量、不写文件、不打印)。
1# ❌ 非纯函数:依赖外部状态 2total = 0 3def add_to_total(x): 4 global total 5 total += x # 修改了外部变量,有副作用 6 return total 7 8# ✅ 纯函数:只依赖输入,不改变外界 9def add(x, y): 10 return x + y # 给定 x=1, y=2,永远返回 3 11
纯函数的好处是极易测试——你不需要准备任何环境,直接喂输入看输出就行。
2. 不可变数据(Immutability)
函数式编程倾向于不修改原始数据,而是返回新的数据结构。
1# ❌ 命令式风格:直接修改列表 2def double_items_imperative(lst): 3 for i in range(len(lst)): 4 lst[i] *= 2 # 原地修改,危险! 5 return lst 6 7# ✅ 函数式风格:返回新列表,原列表不变 8def double_items_functional(lst): 9 return [x * 2 for x in lst] 10 11original = [1, 2, 3] 12result = double_items_functional(original) 13print(original) # [1, 2, 3] ← 原数据安然无恙 14print(result) # [2, 4, 6] 15
3. Lambda 匿名函数
Lambda 是一种一行写完的轻量函数,适合在需要临时传递简单逻辑的场合。
1# 普通函数 2def square(x): 3 return x ** 2 4 5# 等价的 lambda 6square = lambda x: x ** 2 7 8# 多参数 lambda 9multiply = lambda x, y: x * y 10print(multiply(3, 4)) # 12 11 12# 常见用法:作为排序 key 13students = [("Alice", 85), ("Bob", 92), ("Charlie", 78)] 14sorted_students = sorted(students, key=lambda s: s[1], reverse=True) 15print(sorted_students) 16# [('Bob', 92), ('Alice', 85), ('Charlie', 78)] 17
4. 高阶函数:map、filter、reduce
这三个是函数式编程的"三板斧",思路是把操作逻辑和数据分离。
1from functools import reduce 2 3numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 4 5# map:对每个元素做变换,返回新序列 6squares = list(map(lambda x: x ** 2, numbers)) 7print(squares) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 8 9# filter:筛选满足条件的元素 10evens = list(filter(lambda x: x % 2 == 0, numbers)) 11print(evens) # [2, 4, 6, 8, 10] 12 13# reduce:将序列"折叠"成单个值(累积计算) 14total = reduce(lambda acc, x: acc + x, numbers) 15print(total) # 55(即 1+2+...+10) 16 17# 组合使用:先筛选偶数,再求平方,再求和 18result = reduce( 19 lambda acc, x: acc + x, 20 map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, numbers)) 21) 22print(result) # 220(即 4+16+36+64+100) 23
5. 高阶函数与闭包(Closure)
高阶函数可以接收函数作为参数,也可以返回函数。闭包是高阶函数的一种特殊形式——内层函数"记住"了外层函数的变量。
1# 高阶函数:接收函数作为参数 2def apply_twice(func, value): 3 return func(func(value)) 4 5print(apply_twice(lambda x: x + 3, 10)) # 16(10+3=13,13+3=16) 6 7# 闭包:工厂函数,返回一个"记住"了 n 的函数 8def make_multiplier(n): 9 def multiplier(x): 10 return x * n # 这里的 n 被"捕获"了 11 return multiplier 12 13double = make_multiplier(2) 14triple = make_multiplier(3) 15 16print(double(5)) # 10 17print(triple(5)) # 15 18print(double(triple(4))) # 24(先×3得12,再×2得24) 19
6. 装饰器(Decorator)
装饰器本质上是包裹函数的高阶函数,用来在不修改原函数的前提下增加功能。这是函数式思想在 Python 中最优雅的体现之一。
1import time 2 3# 定义一个计时装饰器 4def timer(func): 5 def wrapper(*args, **kwargs): 6 start = time.time() 7 result = func(*args, **kwargs) # 调用原函数 8 end = time.time() 9 print(f"{func.__name__} 耗时 {end - start:.4f} 秒") 10 return result 11 return wrapper 12 13# 用 @ 语法糖应用装饰器 14@timer 15def slow_sum(n): 16 return sum(range(n)) 17 18slow_sum(10_000_000) 19# slow_sum 耗时 0.3241 秒 20
7. functools 与 itertools:函数式工具箱
Python 标准库为函数式编程提供了两个强力模块。
1from functools import partial, lru_cache 2from itertools import chain, takewhile, islice 3 4# --- functools.partial:固定部分参数,生成新函数 --- 5def power(base, exp): 6 return base ** exp 7 8square = partial(power, exp=2) 9cube = partial(power, exp=3) 10 11print(square(5)) # 25 12print(cube(3)) # 27 13 14# --- functools.lru_cache:缓存纯函数结果(记忆化) --- 15@lru_cache(maxsize=None) 16def fibonacci(n): 17 if n < 2: 18 return n 19 return fibonacci(n - 1) + fibonacci(n - 2) 20 21print(fibonacci(50)) # 12586269025,瞬间完成(无缓存会极慢) 22 23# --- itertools:惰性处理大数据 --- 24# chain:拼接多个可迭代对象 25combined = list(chain([1, 2, 3], [4, 5], [6])) 26print(combined) # [1, 2, 3, 4, 5, 6] 27 28# takewhile:取满足条件的前缀元素 29data = [2, 4, 6, 7, 8, 10] 30result = list(takewhile(lambda x: x % 2 == 0, data)) 31print(result) # [2, 4, 6](遇到 7 就停了) 32 33# islice:惰性切片,适合超大数据流 34def infinite_counter(start=0): 35 while True: 36 yield start 37 start += 1 38 39first_10 = list(islice(infinite_counter(), 10)) 40print(first_10) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 41
8. 函数组合(Function Composition)
把多个小函数串联成一条流水线,是函数式编程最迷人的地方。
1from functools import reduce 2 3# 手写 compose:从右到左依次应用函数 4def compose(*funcs): 5 return reduce(lambda f, g: lambda x: f(g(x)), funcs) 6 7# 定义几个小函数 8strip_spaces = lambda s: s.strip() 9to_upper = lambda s: s.upper() 10add_exclaim = lambda s: s + "!!!" 11 12# 组合成流水线 13shout = compose(add_exclaim, to_upper, strip_spaces) 14print(shout(" hello world ")) # HELLO WORLD!!! 15
📊 核心概念速查表
| 概念 | 一句话解释 | Python 实现方式 |
|---|---|---|
| 纯函数 | 无副作用,输入决定输出 | 普通 def,避免全局变量 |
| 不可变数据 | 不修改原数据,返回新数据 | tuple、列表推导式 |
| Lambda | 一行匿名函数 | lambda x: x+1 |
| map / filter | 变换 / 筛选序列 | 内置函数 |
| reduce | 将序列折叠为单值 | functools.reduce |
| 闭包 | 函数记住外部变量 | 嵌套函数 |
| 装饰器 | 包裹函数增强功能 | @decorator 语法 |
| partial | 固定部分参数 | functools.partial |
| 记忆化 | 缓存纯函数结果 | functools.lru_cache |
| 惰性求值 | 按需计算,节省内存 | itertools、生成器 |
💡 写在最后
函数式编程不是要你抛弃 Python 的其他特性,而是给你多一把刀。纯函数让代码可预测,不可变数据减少 bug,高阶函数让逻辑复用变得优雅。 实际项目里,最好的做法是混合使用——用面向对象管理复杂状态,用函数式处理数据变换流程。MIT 的课程材料把 map/filter/reduce 称为"序列操作的三驾马车",而 Python 官方文档也专门为此写了一份 Functional Programming HOWTO,值得深读。
从今天起,每次写 for 循环处理列表时,不妨停一秒问自己:这里能不能用一个 map 或列表推导式替代?答案往往是肯定的。
参考来源:
- MIT 6.005 课程 & Python 官方 Functional Programming HOWTO — docs.python.org/3/howto/fun…
- Medium — Lambda, Map, Filter & Reduce in Python
- Reddit r/Python — Functional programming concepts that actually work in Python
- adabeat.com — Functional Programming in Python
《Python 函数式编程:从思想到实践》 是转载文章,点击查看原文。
