当函数参数顺序不影响结果时,如何部署缓存?
实现交换律函数的缓存忽略参数顺序
当然可以,核心思路是统一缓存键的参数顺序,让func(a,b)和func(b,a)生成相同的缓存键,从而复用已有缓存。以下是几种实用方案:
方案1:在函数内部标准化参数顺序
直接在被缓存的函数里先调整参数顺序,确保每次处理的参数都是固定顺序的:
from functools import cache @cache def func(a, b): # 标准化参数顺序:保证a <= b(需参数支持比较操作) if a > b: a, b = b, a # 原函数逻辑示例 return a + b
如果参数是不可直接比较的自定义对象,可以给对象实现__lt__方法,或者用sorted结合自定义key:
from functools import cache class Item: def __init__(self, id): self.id = id def __hash__(self): return hash(self.id) def __lt__(self, other): # 基于id属性比较排序 return self.id < other.id @cache def func(item1, item2): # 用sorted统一参数顺序 item_a, item_b = sorted([item1, item2]) # 原函数逻辑 return item_a.id + item_b.id
方案2:自定义交换律缓存装饰器
如果不想修改原函数逻辑,可以封装一个专门的装饰器,自动处理参数排序后再缓存:
from functools import cache, wraps def commutative_cache(func): @wraps(func) def wrapper(*args): # 对传入的参数排序,生成统一的参数元组 sorted_args = tuple(sorted(args)) # 内部定义被缓存的函数,复用原函数逻辑 @cache def cached_func(*sorted_args): return func(*sorted_args) return cached_func(*sorted_args) return wrapper # 使用装饰器 @commutative_cache def func(a, b): return a + b
这个装饰器支持任意数量的交换律参数(只要参数可哈希、可排序),而且不会污染原函数的代码逻辑。
注意事项
- 所有参数必须是可哈希的:这是
@cache的基本要求,否则无法生成缓存键。 - 参数需支持排序:如果是自定义对象,需实现
__lt__方法,或者在sorted中指定key参数来定义排序规则。
内容的提问来源于stack exchange,提问作者jonnybolton16
相关产品推荐
相关产品推荐

