考虑一个函数f(*x)
,它需要很多参数*x
。基于这些参数(对象),函数f
组成一个相当复杂的对象o
并返回它。 o
实现了__call__
,因此o
本身就是一个函数。由于o
的组合非常耗时,并且在我的场景中,基于相同的参数o
有多个*x
实例是没有意义的,因此它们将被缓存。
现在的问题是:如何基于多个参数*x
有效地计算哈希值?目前我正在使用python字典,并且我连接每个str()
的{{1}}表示来构建每个键。它适用于我的场景,但感觉相当尴尬。我需要以非常高的频率调用结果对象x
,所以我怀疑o
的重复调用和字符串连接会浪费大量的计算时间。
答案 0 :(得分:2)
您可以使用hash
内置函数,将x
中项目的哈希值组合在一起。执行此操作的典型方法(请参阅例如the documentation)将跨越各个对象的所有哈希值xor
:
建议以某种方式混合(例如使用exclusive或)对象组件的哈希值,这些哈希值也在对象的比较中起作用
要以功能性方式实现这一点,请使用operator
和reduce
:
from functools import reduce # only required in Python 3.x
from operator import xor
def hashed(*x):
return reduce(xor, map(hash, x))
答案 1 :(得分:2)
从版本3.2开始,Python已经包含了一个可以使用的LRU缓存实现
根据参数缓存函数的结果:
functools.lru_cache
示例:
from functools import lru_cache
@lru_cache(maxsize=32)
def f(*args):
"""Expensive function
"""
print("f(%s) has been called." % (args, ))
return sum(args)
print(f(1, 2, 3))
print(f(1, 2, 3, 4))
print(f(1, 2, 3))
print(f.cache_info())
输出:
f((1, 2, 3)) has been called.
6
f((1, 2, 3, 4)) has been called.
10
6
CacheInfo(hits=1, misses=2, maxsize=32, currsize=2)
(注意f(1, 2, 3)
仅被调用一次)
正如评论中所建议的那样,最好只使用参数的hash()
来为你的参数构建缓存键 - 这就是lru_cache
已经为你做的事情。
如果您仍然使用Python 2.7,Raymond Hettinger已经发布了一些您可以在自己的代码中使用的recipes with LRU caches。