我正在编写一种方法来生成用于缓存函数结果的缓存键,该键基于函数名和参数哈希值的组合。
目前我使用hashlib来散列参数的序列化版本,但序列化大型对象的操作非常昂贵,那么还有什么选择呢?
#get the cache key for storage
def cache_get_key(*args):
import hashlib
serialise = []
for arg in args:
serialise.append(str(arg))
key = hashlib.md5("".join(serialise)).hexdigest()
return key
更新: 我尝试使用hash(str(args)),但是如果args中包含相对较大的数据,则仍然需要很长时间来计算哈希值。有没有更好的方法呢?
实际上,带有大数据的str(args)需要永远......
答案 0 :(得分:1)
您是否尝试过使用hash
功能?它在元组上运行得非常好。
答案 1 :(得分:1)
假设您创建了对象,并且它由较小的组件组成(它不是二进制blob),则可以在使用其子组件的哈希值构建对象时预先计算哈希值。
例如,不是serialize(repr(arg))
,而是arg.precomputedHash if isinstance(arg, ...) else serialize(repr(arg))
如果你既不制作自己的对象也不使用hash
能够对象,你可以保留一个对象参考的记忆表 - >哈希,假设你不改变对象。最糟糕的情况是,你可以使用一种允许记忆的函数式语言,因为这种语言中的所有对象都可能是不可变的,因此可以编辑。
答案 2 :(得分:1)
def cache_get_key(*args):
return hash(str(args))
或(如果你真的想使用hashlib库)
def cache_get_key(*args):
return hashlib.md5(str(args)).hexdigest()
我不打算重写代码以使数组成为字符串。使用内置的。
以下是@ 8bitwide建议的解决方案。这个解决方案根本不需要散列!
def foo(x, y):
return x+y+1
result1 = foo(1,1)
result2 = foo(2,3)
results = {}
results[foo] = {}
results[foo][ [1,1] ] = result1
results[foo][ [2,3] ] = result2
答案 3 :(得分:0)
我看到人们将任意python对象提供给random.seed(),然后使用random.random()中的第一个值作为" hash"值。它没有给出极好的值分布(可以是倾斜的),但它似乎适用于任意对象。
如果你不需要加密强度哈希,我想出了一对哈希函数,用于我在bloom过滤器中使用的整数列表。他们出现在下面。布隆过滤器实际上使用这两个散列函数的线性组合来获得任意大量的散列函数,但是它们应该在其他需要稍微分散且具有良好分布的上下文中正常工作。他们的灵感来自Knuth关于线性同余随机数生成的文章。他们将整数列表作为输入,我相信这可能只是序列化字符的ord()。
MERSENNES1 = [ 2 ** x - 1 for x in [ 17, 31, 127 ] ]
MERSENNES2 = [ 2 ** x - 1 for x in [ 19, 67, 257 ] ]
def simple_hash(int_list, prime1, prime2, prime3):
'''Compute a hash value from a list of integers and 3 primes'''
result = 0
for integer in int_list:
result += ((result + integer + prime1) * prime2) % prime3
return result
def hash1(int_list):
'''Basic hash function #1'''
return simple_hash(int_list, MERSENNES1[0], MERSENNES1[1], MERSENNES1[2])
def hash2(int_list):
'''Basic hash function #2'''
return simple_hash(int_list, MERSENNES2[0], MERSENNES2[1], MERSENNES2[2])