functools 模块是 Python 标准库中用于高阶函数的工具集,主要提供函数式编程的支持。下面详细介绍该模块的主要功能和使用方法。
1. 模块导入
import functools
2. reduce() 函数
reduce() 函数用于对序列中的元素进行累积操作。
基本用法:
import functools
# 计算阶乘
result = functools.reduce(lambda x, y: x * y, range(1, 6))
print(result)
# 输出: 120
# 字符串连接
words = ['Python', 'is', 'awesome']
sentence = functools.reduce(lambda x, y: x + ' ' + y, words)
print(sentence)
# 输出: Python is awesome
此代码部分语法与关键信息无需改动,已较为规范,仅在注释处可适当优化表述,以增强可读性与书面性。上述代码中,注释部分使用了“计算阶乘”“字符串连接”等表述,使代码的功能意图更加清晰明确。

带初始值:
# 具备初始值的累加操作
numbers = [1, 2, 3, 4]
total = functools.reduce(lambda x, y: x + y, numbers, 10)
print(total)
# 输出: 20 (即 10 + 1 + 2 + 3 + 4 之和)
3. partial() 函数
partial() 用于部分应用函数参数,创建新的可调用对象。
基本用法:
import functools
# 定义乘法函数
def multiply(x, y):
return x * y
# 构建固定首个参数的新函数
double = functools.partial(multiply, 2)
print(double(5))
# 输出: 10
# 构建固定第二个参数的新函数
triple = functools.partial(multiply, y=3)
print(triple(4))
# 输出: 12
实际应用示例:
import functools
# 1. 简化函数调用
# 定义幂运算函数
def power(base, exponent):
return base ** exponent
# 创建用于计算平方的函数
square = functools.partial(power, exponent=2)
# 创建立方函数
cube = functools.partial(power, exponent=3)
print(square(5))
# 输出: 25
print(cube(3))
# 输出: 27
# 2. 处理默认参数
# 定义问候函数
def greet(name, message="Hello"):
return f"{message}, {name}!"
# 创建特定的问候函数
say_hello = functools.partial(greet, message="Hello")
say_hi = functools.partial(greet, message="Hi")
say_hey = functools.partial(greet, message="Hey")
print(say_hello("Alice"))
# 输出: Hello, Alice!
print(say_hi("Bob"))
# 输出: Hi, Bob!
4. lru_cache 装饰器
lru_cache 提供最近最少使用缓存,用于函数结果缓存,提升性能。
基本用法:
import functools
import time
# 运用 LRU 缓存机制对斐波那契函数进行优化
@functools.lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
# 开展性能测试
start_time = time.time()
result = fibonacci(35)
end_time = time.time()
print(f"斐波那契数列第 35 项的值为: {result}")
print(f"此次计算耗时: {end_time - start_time:.4f} 秒")
缓存参数配置:
import functools
# 配置无大小限制的缓存机制
@functools.lru_cache(maxsize=None)
def expensive_operation(x):
print(f"正在计算 {x}...")
return x * x
# 进行功能测试
print(expensive_operation(5))
# 首次调用,会打印“正在计算 5...”
print(expensive_operation(5))
# 后续调用,直接从缓存返回结果,不会再次打印计算信息
# 配置带参数的缓存机制,最大缓存容量为 32
@functools.lru_cache(maxsize=32)
def configurable_operation(a, b, option=True):
print(f"正在执行操作: a={a}, b={b}, option={option}")
return a + b if option else a * b
print(configurable_operation(2, 3))
# 首次调用,会执行计算并打印操作信息
print(configurable_operation(2, 3))
# 一样参数的后续调用,从缓存返回结果
print(configurable_operation(2, 3, False))
# 不同参数的调用,会重新执行计算
5. wraps 装饰器
wraps 用于保留被装饰函数的元数据。
问题演示:
# 定义装饰器函数
def my_decorator(func):
def wrapper(*args, **kwargs):
"""此为包装器的文档说明"""
return func(*args, **kwargs)
return wrapper
# 使用装饰器修饰示例函数
@my_decorator
def example():
"""这是示例函数的文档说明"""
pass
# 打印函数的名称和文档字符串
print(example.__name__)
# 输出: wrapper
print(example.__doc__)
# 输出: 此为包装器的文档说明
使用 wraps 解决问题:
import functools
# 定义装饰器函数,借助 functools.wraps 保留原函数元信息
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
"""此为包装器的详细文档说明"""
return func(*args, **kwargs)
return wrapper
# 使用自定义装饰器修饰示例函数
@my_decorator
def example():
"""这是示例函数的详尽文档说明"""
pass
# 打印函数的名称和文档字符串,因使用 wraps 保留元信息,输出为原函数相关内容
print(example.__name__)
# 输出: example
print(example.__doc__)
# 输出: 这是示例函数的详尽文档说明
6. total_ordering 装饰器
total_ordering 自动生成缺失的比较方法。
基本用法:
import functools
# 运用 functools.total_ordering 装饰器,为类自动生成比较方法
@functools.total_ordering
class Student:
def __init__(self, name, score):
# 初始化学生对象,包含姓名和分数属性
self.name = name
self.score = score
def __eq__(self, other):
# 定义相等比较方法,依据学生分数来判断
return self.score == other.score
def __lt__(self, other):
# 定义小于比较方法,根据学生分数进行比较
return self.score < other.score
# 创建两个学生对象
student1 = Student("Alice", 85)
student2 = Student("Bob", 92)
# 进行各种比较操作并输出结果
print(student1 < student2)
# 输出: True
print(student1 <= student2)
# 输出: True
print(student1 > student2)
# 输出: False
print(student1 >= student2)
# 输出: False
print(student1 == student2)
# 输出: False
7. cmp_to_key 函数
cmp_to_key 将老式比较函数转换为 key 函数。
使用示例:
import functools
# 定义老式的比较函数,通过两数相减来判断大小关系
def numeric_compare(x, y):
return x - y
# 构建现代风格的比较函数,以 -1、1 和 0 明确表明大小关系
def modern_compare(x, y):
"""此为现代风格的比较函数,用于比较两个元素的大小"""
if x < y:
return -1
elif x > y:
return 1
else:
return 0
# 准备待排序的数字列表
numbers = [5, 2, 8, 1, 9]
# 利用 functools.cmp_to_key 将现代比较函数转换为适用于 sorted 函数的 key 函数进行排序
sorted_numbers = sorted(numbers, key=functools.cmp_to_key(modern_compare))
print(sorted_numbers)
# 输出按升序排列的数字列表:[1, 2, 5, 8, 9]
# 定义复杂的自定义比较函数,先按元素长度比较,长度一样时再按字母顺序比较
def custom_compare(a, b):
"""该比较函数先比较元素的长度,若长度不同则按长度排序;长度一样时,再按字母顺序排序"""
if len(a) != len(b):
return len(a) - len(b)
elif a < b:
return -1
elif a > b:
return 1
else:
return 0
# 准备待排序的单词列表
words = ['apple', 'banana', 'cherry', 'date', 'elderberry']
# 同样使用 functools.cmp_to_key 转换自定义比较函数后对单词列表进行排序
sorted_words = sorted(words, key=functools.cmp_to_key(custom_compare))
print(sorted_words)
8. singledispatch 装饰器
singledispatch 实现函数重载(单分派泛函数)。
基本用法:
import functools
# 运用 functools.singledispatch 实现单分派泛函数
@functools.singledispatch
def process(arg):
"""
此为默认的处理函数,当传入的参数类型未被其他注册函数匹配时执行
"""
print(f"执行默认处理流程: {arg}")
# 注册针对整数类型的处理函数
@process.register
def _(arg: int):
"""
专门处理整数类型参数的函数
"""
print(f"针对整数进行处理: {arg}")
# 注册针对字符串类型的处理函数
@process.register
def _(arg: str):
"""
专门处理字符串类型参数的函数
"""
print(f"针对字符串进行处理: {arg}")
# 注册针对列表类型的处理函数
@process.register
def _(arg: list):
"""
专门处理列表类型参数的函数,会输出列表的长度
"""
print(f"对列表进行处理,其长度为: {len(arg)}")
# 测试不同类型参数的处理情况
process(42)
# 输出: 针对整数进行处理: 42
process("hello")
# 输出: 针对字符串进行处理: hello
process([1, 2, 3])
# 输出: 对列表进行处理,其长度为: 3
process(3.14)
# 输出: 执行默认处理流程: 3.14
9. 实际应用案例
案例 1:性能优化缓存
import functools
import time
# 利用 functools.lru_cache 装饰器,设置最大缓存大小为 100,对函数结果进行缓存
@functools.lru_cache(maxsize=100)
def expensive_api_call(user_id):
"""
此函数用于模拟一次代价高昂的 API 调用,会产生必定的网络延迟
"""
time.sleep(1) # 模拟网络延迟所耗费的时间
return f"用户 {user_id} 的相关数据"
# 测试缓存机制的实际效果
start_time = time.time()
# 首次调用函数,由于没有缓存,会执行完整的 API 调用流程,大约耗时 1 秒
print(expensive_api_call(1))
# 再次以一样参数调用函数,此时结果已被缓存,会直接从缓存中获取,几乎瞬间完成
print(expensive_api_call(1))
# 传入新的参数调用函数,由于缓存中没有该结果,会再次执行完整的 API 调用,大约耗时 1 秒
print(expensive_api_call(2))
end_time = time.time()
# 输出整个测试过程所花费的总时间,保留两位小数
print(f"总耗时: {end_time - start_time:.2f} 秒")
案例 2:装饰器工具函数
import functools
import time
# 定义计时装饰器,用于准确测量函数的执行时间
def timer(func):
"""
此为计时装饰器,可准确记录并输出被装饰函数的执行时长
"""
@functools.wraps(func)
def wrapper(*args, **kwargs):
# 记录函数开始执行的时间
start_time = time.time()
# 调用被装饰的函数并获取结果
result = func(*args, **kwargs)
# 记录函数执行结束的时间
end_time = time.time()
# 输出函数执行的时间,准确到小数点后四位
print(f"函数 {func.__name__} 的执行时间为: {end_time - start_time:.4f} 秒")
return result
return wrapper
# 定义重试装饰器,允许函数在执行失败时进行重试
def retry(max_attempts=3, delay=1):
"""
此为重试装饰器,当被装饰的函数执行出现异常时,会尝试重新执行指定次数
"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
# 循环尝试执行函数,最多尝试 max_attempts 次
for attempt in range(max_attempts):
try:
# 尝试执行被装饰的函数
return func(*args, **kwargs)
except Exception as e:
# 如果达到最大尝试次数,抛出异常
if attempt == max_attempts - 1:
raise e
# 输出当前尝试失败的信息,并提示将在指定延迟后重试
print(f"第 {attempt + 1} 次尝试失败,将在 {delay} 秒后重试,错误信息为: {e}")
# 等待指定的延迟时间
time.sleep(delay)
return None
return wrapper
return decorator
# 使用计时装饰器和重试装饰器装饰不可靠操作函数
@timer
@retry(max_attempts=3, delay=1)
def unreliable_operation():
"""
该函数用于模拟一个不可靠的操作,有必定概率执行失败
"""
import random
# 以 70% 的概率抛出异常
if random.random() < 0.7:
raise Exception("随机失败")
return "操作成功"
# 测试不可靠操作函数
print(unreliable_operation())
案例 3:函数组合
import functools
# 定义函数组合功能,该功能允许将多个函数按照从右到左的顺序依次嵌套调用
# 例如,compose(f, g, h)(x) 等价于 f(g(h(x)))
def compose(*functions):
"""
此函数实现了函数组合的功能,可按照传入函数的顺序,将多个函数进行组合。
组合后的函数会依次对输入参数执行各函数的操作。
"""
return functools.reduce(lambda f, g: lambda x: f(g(x)), functions)
# 定义几个简单的基础函数
# 该函数用于对输入的数值加 1
def add_one(x):
return x + 1
# 此函数用于将输入的数值乘以 2
def multiply_by_two(x):
return x * 2
# 该函数用于计算输入数值的平方
def square(x):
return x ** 2
# 进行函数组合操作,将 add_one、multiply_by_two 和 square 这三个函数进行组合
# 组合后的函数按照 square -> multiply_by_two -> add_one 的顺序对输入进行处理
complex_operation = compose(add_one, multiply_by_two, square)
# 调用组合后的函数,传入参数 3,并获取计算结果
result = complex_operation(3)
# 输出最终的计算结果
print(f"计算结果为: {result}")
# 详细计算过程为:3 的平方是 9,9 乘以 2 得到 18,18 加 1 等于 19
10. 缓存统计信息
对于 lru_cache,可以查看缓存统计信息:
import functools
# 定义一个带有缓存功能的函数,使用 functools.lru_cache 装饰器,设置最大缓存大小为 3
# 该函数用于计算输入参数的平方
@functools.lru_cache(maxsize=3)
def cached_function(x):
return x * x
# 调用该函数,依次传入不同的参数
cached_function(1)
cached_function(2)
cached_function(3)
# 再次传入之前使用过的参数 1,此时应命中缓存
cached_function(1)
# 传入新的参数 4,由于缓存已满,会触发缓存淘汰机制
cached_function(4)
# 查看当前缓存的相关信息,包括命中次数、未命中次数、最大缓存大小和当前缓存大小
print(f"当前缓存信息为: {cached_function.cache_info()}")
# 预期输出示例: CacheInfo(hits=1, misses=4, maxsize=3, currsize=3)
# 清空缓存中的所有条目
cached_function.cache_clear()
# 再次查看缓存信息,此时命中次数、未命中次数和当前缓存大小应重置为 0
print(f"缓存清空后信息为: {cached_function.cache_info()}")
# 预期输出: CacheInfo(hits=0, misses=0, maxsize=3, currsize=0)

总结
functools 模块提供了强劲的函数式编程工具:
- reduce(): 序列累积操作
- partial(): 部分应用函数参数
- lru_cache: 函数结果缓存,提升性能
- wraps: 保留装饰函数的元数据
- total_ordering: 自动生成比较方法
- cmp_to_key: 转换老式比较函数
- singledispatch: 函数重载支持
这些工具使得 Python 代码更加简洁、高效和可维护,特别适合函数式编程风格和性能优化场景。
© 版权声明
文章版权归作者所有,未经允许请勿转载。

收藏了,感谢分享