Python函数式编程:推荐使用functools模块
Python 是一种多范式(multi-paradigm)编程语言,它同时支持面向对象编程(Object-Oriented Programming)、过程式编程(Procedural Programming)和函数式编程(Functional Programming)。函数式编程是一种基于数学函数的编程范式,它的特点是强调函数的纯净性(purity),即输入参数一致,输出结果一定一致,避免副作用(side-effect)。
在 Python 中,函数即为对象,可以被作为参数传递给其他函数,或者被作为返回值返回。函数式编程利用了这一点,许多函数都可以接收函数作为参数,或者返回函数作为返回值。在 Python 标准库中,functools 模块(Python 2.x 中是 functools 模块,Python 3.x 中是 _functools 模块)提供了一些常用的函数式编程工具,本文将介绍它们的用法。
1. functools.partial——偏函数
functools.partial 是一个高阶函数(higher-order function),它的作用是“冻结”(partial)函数的部分参数,返回一个新的函数。它的用法如下所示:
from functools import partial
def func(a, b, c):
return a + b + c
add_1_and_2 = partial(func, 1, 2)
result = add_1_and_2(3) # result is 6
在上面的例子中,add_1_and_2 是一个新函数,它的参数列表只包含一个参数 c,而且 func 函数的前两个参数已经被“冻结”为 1 和 2。当 add_1_and_2 被调用时,它会自动把 1 和 2 传递给 func 函数作为前两个参数,而将调用者传递的参数作为第三个参数传递给 func 函数。因此,以上面的例子为例,add_1_and_2(3) 的结果是 1 + 2 + 3 = 6。
2. functools.reduce——归约函数
functools.reduce 是一个归约函数(reduce function),它的作用是将一个序列(sequence)中的所有元素归纳为一个单独的值。归约函数的典型应用场景是累加(sum)和乘积(product)。它的用法如下所示:
from functools import reduce lst = [1, 2, 3, 4, 5] sum_of_lst = reduce(lambda x, y: x + y, lst) # sum_of_lst is 15 product_of_lst = reduce(lambda x, y: x * y, lst) # product_of_lst is 120
在上面的例子中,reduce 函数接收两个参数:一个归纳函数和一个序列。归纳函数接收两个参数,它们代表序列中的相邻元素,当归纳函数被调用时,它会产生一个新的值,以便与接下来的一个元素进行处理,最终产生一个单独的值。在上面的例子中,lambda x, y: x + y 和 lambda x, y: x * y 分别代表了归纳函数,它们实现的是对序列求和和求积的功能。
需要注意的是,Python 3.x 中的 reduce 函数被移动到了 functools 模块中,Python 2.x 中的 reduce 函数是内置函数。
3. functools.cache——缓存装饰器
functools.cache 装饰器用于给函数添加缓存机制,可以避免多次计算同样的结果。它的用法非常简单:
from functools import cache
@cache
def fib(n):
if n <= 1:
return n
else:
return fib(n-1) + fib(n-2)
result = fib(50) # result is 12586269025
在上面的例子中,我们定义了一个斐波那契数列的函数 fib(n),当计算 fib(n) 时,它会通过递归方式计算 fib(n-1) 和 fib(n-2) 的值,最终得到 fib(n) 的值。由于计算 fib(n-1) 和 fib(n-2) 的值会重复多次,因此可以使用 functools.cache 装饰器来缓存 fib(n-1) 和 fib(n-2) 的值,减少计算量。当再次计算 fib(n-1) 或 fib(n-2) 时,函数会从缓存中获取已经计算过的值,避免多次重复计算。
需要注意的是,functools.cache 装饰器是 Python 3.9 中新增的功能,在 Python 3.9 以下的版本中无法使用。
4. functools.lru_cache——LRU 缓存装饰器
functools.lru_cache 装饰器也用于给函数添加缓存机制,不同的是它采用 LRU(Least Recently Used)算法来清理缓存,可以避免缓存空间被占满。它的用法与 functools.cache 装饰器类似:
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
if n <= 1:
return n
else:
return fib(n-1) + fib(n-2)
result = fib(50) # result is 12586269025
在上面的例子中,我们定义了一个斐波那契数列的函数 fib(n),使用 functools.lru_cache 装饰器来添加缓存机制。maxsize 参数指定了最大缓存数量,当缓存数量超过这个值时,较早缓存的值将会被清理。如果 maxsize 参数被省略或者被设置为 None,那么缓存数量将不会受限制。在实际应用中,如果缓存大小对于性能有很大影响,可以通过试验得到最合适的 maxsize 值。
需要注意的是,functools.lru_cache 装饰器是 Python 3.2 中新增的功能,在 Python 3.2 以下的版本中无法使用。
总结
functools 模块提供的函数式编程工具,可以让 Python 开发者更加方便地编写函数式代码。其中,functools.partial 函数可以帮助开发者通过“冻结”函数参数实现代码复用,functools.reduce 函数可以帮助开发者将序列中的元素归纳为一个单独的值,functools.cache 装饰器可以帮助开发者添加缓存机制,避免多次计算同样的结果,functools.lru_cache 装饰器可以帮助开发者添加 LRU 缓存机制,避免缓存空间被占满。这些工具都是 Python 开发中不可或缺的。
