How to hash *args **kwargs for function cache?
I'm working with xlwt
which has a 4k limit on how many styles can be defined in an excel doc.
Normally, one creates styles like so:
style = xlwt.easyxf("font: bold 1")
Which I simply replaced with
def cached_easyxf(self, format):
return self._cache.setdefault(format, xlwt.easyxf(format))
Which works perfectly. Now, I've found out that I need to pass in keyword arguments sometimes which got me thinking: how should I hash the args/kwargs signature?
Should I create a cache key based on str(value)? Pickle? What's most robust?
For my situation it looks like I can just convert key/values to strings and add it to my keys... but I'm now curious about a generic way to handle this with say unhashable types like arg=[1, 2, 3]
def cached_call(*args, **kwargs):
return cache.get(what_here)
cached_call('hello')
cached_call([1, 2, 3], {'1': True})
Here is the technique used in functools.lru_cache():
kwd_mark = object() # sentinel for separating args from kwargs
def cached_call(*args, **kwargs):
key = args + (kwd_mark,) + tuple(sorted(kwargs.items()))
return cache.get(key)
Note, the above code handles keyword arguments but makes no attempt to handle non-hashable values like lists. Your idea for using the str of a list is a reasonable start. For set objects, you would need to sort the entries first, str(sorted(someset))
. Other objects may not have a useful __repr__ or __str__ (ie they may show only the object type and location in memory). In summary, handling arbitrary unhashable arguments requires careful consideration of each object type.
上一篇: 为什么不**解压函数调用kwargs?