functools 是python标准库中用于高阶函数操作的核心模块,提供函数式编程工具(如装饰器、部分函数应用、缓存等)本文将探索 functools 模块所有公开方法的功能、使用场景、代码示例、输出结果!
|
方法 |
核心用途 |
版本要求 |
典型场景 |
|
reduce |
累积计算 |
所有版本 |
求和/乘积 |
|
partial/partialmethod |
参数固定 |
所有版本 |
柯里化、简化调用 |
|
wraps/update_wrapper |
装饰器元数据维护 |
所有版本 |
自定义装饰器 |
|
lru_cache/cache |
结果缓存 |
cache: 3.9+ |
递归优化、I/O 缓存 |
|
cached_property |
属性缓存 |
3.8+ |
开销大的属性计算 |
|
total_ordering |
比较方法生成 |
所有版本 |
自定义类比较 |
|
singledispatch/method |
类型分派 |
method: 3.8+ |
多类型统一处理 |
|
cmp_to_key |
比较函数转换 |
所有版本 |
兼容旧版排序逻辑 |
1.functools.reduce(function, iterable[, initializer])
功能:将二元函数 function 累积应用于 iterable 的元素,从左到右,将序列缩减为单个值。
参数:
- function:接受两个参数的函数(如 lambda x, y: x + y)
- iterable:可迭代对象(如列表)
- initializer(可选):初始值,若提供则作为第一次调用的左参数
使用场景:替代循环实现累积计算(如求和、阶乘)。
from functools import reduce
# 示例1:计算列表元素和
result = reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])
print(result) # 输出: 15 (计算过程: (((1+2)+3)+4)+5)
# 示例2:带初始值的乘积
result = reduce(lambda x, y: x * y, [1, 2, 3], 10)
print(result) # 输出: 60 (计算过程: (10*1)*2*3)
2.functools.partial(func, *args, **keywords)
功能:固定函数 func 的部分参数,返回一个新 **可调用对象**(偏函数)。
参数:
- func:原始函数
- *args:位置参数固定值
- **keywords:关键字参数固定值
使用场景:简化函数调用(如固定配置参数)、柯里化。
from functools import partial
def power(base, exponent):
return base ** exponent
# 固定 base=2,创建计算平方的新函数
square = partial(power, exponent=2)
print(square(4)) # 输出: 16
# 固定 exponent=3,创建计算立方的新函数
cube = partial(power, exponent=3)
print(cube(3)) # 输出: 27
3.functools.partialmethod(func, *args, **keywords)
功能:与 partial 类似,但专为 **类方法** 设计(需在类内部使用)。
参数:同 partial。
使用场景:在类中定义部分参数固定的方法。
from functools import partialmethod
class Cell:
def set_state(self, state, temporary=False):
print(f"State set to {state}, temporary={temporary}")
# 创建固定 temporary=True 的方法
set_temp_state = partialmethod(set_state, temporary=True)
cell = Cell()
cell.set_temp_state("active") # 输出: State set to active, temporary=True
4.functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
功能:将 wrapped 函数的元数据(如 __name__, __doc__)复制到 wrapper 函数。
参数:
- wrapper:装饰器函数
- wrapped:被装饰的原始函数
- assigned:需复制的属性列表(默认复制 __name__, __doc__ 等)
- updated:需更新的属性列表(默认更新 __dict__)
使用场景:手动编写装饰器时保留原始函数元信息。
from functools import update_wrapper
def my_decorator(func):
def wrapper(*args, **kwargs):
"""Wrapper docstring"""
return func(*args, **kwargs)
update_wrapper(wrapper, func) # 关键:复制元数据
return wrapper
@my_decorator
def example():
"""Example docstring"""
pass
print(example.__name__) # 输出: example (未复制时会输出 'wrapper')
print(example.__doc__) # 输出: Example docstring
5.functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
功能:update_wrapper 的装饰器版本,用于简化装饰器元数据维护。
参数:同 update_wrapper。
使用场景:所有自定义装饰器的必备工具。
from functools import wraps
def logging_decorator(func):
@wraps(func) # 自动处理元数据复制
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
@logging_decorator
def greet(name):
"""问候函数"""
print(f"Hello, {name}!")
greet("Alice")
# 输出:
# Calling greet
# Hello, Alice!
print(greet.__name__) # 输出: greet
print(greet.__doc__) # 输出: 问候函数
6.functools.lru_cache(maxsize=128, typed=False)
功能:LRU(Least Recently Used)缓存装饰器,缓存函数结果以提升重复调用性能。
参数:
- maxsize:缓存最大条目数(设为 None 表明无限制)
- typed:若 True,区分不同参数类型(如 3 和 3.0 视为不同键)
使用场景:加速递归计算(如斐波那契数列)、避免重复 I/O 操作。
from functools import lru_cache
@lru_cache(maxsize=32)
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(100)) # 输出: 354224848179261915075
print(fibonacci.cache_info()) # 输出缓存统计: CacheInfo(hits=..., misses=..., ...)
7.functools.cached_property(func)
功能:将类方法转换为 缓存属性,首次访问计算值后缓存结果(实例级缓存)。
注意:Python 3.8+ 引入,适用于 实例方法(非类方法)。
使用场景:避免重复计算开销大的属性(如数据库查询结果)。
from functools import cached_property
class Circle:
def __init__(self, radius):
self.radius = radius
@cached_property
def area(self):
print("计算面积...")
return 3.14 * self.radius ** 2
c = Circle(5)
print(c.area) # 输出: 计算面积...
78.5
print(c.area) # 输出: 78.5 (无"计算面积...",说明已缓存)
8.functools.total_ordering(cls)
功能:类装饰器,根据用户定义的 部分比较方法 自动生成完整的比较操作符(<, <=, >, >=)。
要求:必须实现 __eq__ 和 **至少一个** 比较方法(如 __lt__)。
使用场景:简化自定义类的比较逻辑。
from functools import total_ordering
@total_ordering
class Student:
def __init__(self, grade):
self.grade = grade
def __eq__(self, other):
return self.grade == other.grade
def __lt__(self, other):
return self.grade < other.grade
s1 = Student(85)
s2 = Student(90)
print(s1 < s2) # 输出: True
print(s1 <= s2) # 输出: True (由装饰器自动生成)
print(s1 > s2) # 输出: False
9.functools.singledispatch(default)
功能:单分派泛型函数装饰器,根据 第一个参数的类型 动态选择实现(类似函数重载)。
使用场景:处理不同数据类型的统一接口(如序列化函数)。
from functools import singledispatch
@singledispatch
def process(data):
print(f"默认处理: {data}")
@process.register
def _(data: int):
print(f"处理整数: {data * 2}")
@process.register(str)
def _(data):
print(f"处理字符串: {data.upper()}")
process(10) # 输出: 处理整数: 20
process("hello") # 输出: 处理字符串: HELLO
process([1, 2]) # 输出: 默认处理: [1, 2]
10.functools.singledispatchmethod(func)
功能:singledispatch 的方法版本,用于类中的方法。
注意:Python 3.8+ 引入。
使用场景:在类中实现基于参数类型的方法重载。
from functools import singledispatchmethod
class Processor:
@singledispatchmethod
def process(self, data):
print(f"默认处理: {data}")
@process.register
def _(self, data: int):
print(f"处理整数: {data * 2}")
@process.register
def _(self, data: str):
print(f"处理字符串: {data.upper()}")
p = Processor()
p.process(42) # 输出: 处理整数: 84
p.process("test") # 输出: 处理字符串: TEST
11.functools.cmp_to_key(func)
功能:将 Python 2 风格的 比较函数(cmp(a, b) 返回 -1/0/1)转换为 Python 3 的key 函数
参数:func 是比较函数(接受两个参数,返回负数/零/正数)。
使用场景:在 sorted() 中使用旧版比较逻辑。
from functools import cmp_to_key
def compare(a, b):
return (a > b) - (a < b) # 标准 cmp 函数
numbers = [5, 2, 8, 1]
sorted_nums = sorted(numbers, key=cmp_to_key(compare))
print(sorted_nums) # 输出: [1, 2, 5, 8]
# 逆序比较
def reverse_cmp(a, b):
return (b > a) - (b < a)
sorted_reverse = sorted(numbers, key=cmp_to_key(reverse_cmp))
print(sorted_reverse) # 输出: [8, 5, 2, 1]
12.functools.cache()
功能:lru_cache(maxsize=None) 的快捷方式,创建无限制缓存的装饰器。
注意:Python 3.9+ 引入,等价于 @lru_cache(maxsize=None)。
使用场景:需要永久缓存结果的场景(如纯函数计算)。
from functools import cache
@cache
def factorial(n):
return n * factorial(n-1) if n else 1
print(factorial(10)) # 输出: 3628800
print(factorial.cache_info()) # 输出: CacheInfo(hits=..., misses=..., maxsize=None, currsize=11)






收藏了,感谢分享