如何散列* args ** kwargs进行函数缓存?

时间:2012-04-19 01:53:18

标签: python

我正在使用xlwt,它对excel文档中可以定义的样式数量有4k的限制。

通常情况下,会创建一个样式:

style = xlwt.easyxf("font: bold 1")

我简单地用

代替
def cached_easyxf(self, format):
    return self._cache.setdefault(format, xlwt.easyxf(format))

完美无缺。现在,我发现我需要传递关键字参数,这有时让我思考:我应该如何散列args / kwargs签名?

我应该根据str(值)创建缓存键吗?泡菜?什么是最强大的?

对于我的情况,看起来我可以将键/值转换为字符串并将其添加到我的键......但我现在很好奇处理这个问题的通用方法,例如arg=[1, 2, 3]这样的不可用类型

def cached_call(*args, **kwargs):
    return cache.get(what_here)
cached_call('hello')
cached_call([1, 2, 3], {'1': True})

1 个答案:

答案 0 :(得分:15)

这是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)

注意,上面的代码处理关键字参数但不尝试处理像列表这样的不可散列值。您使用列表的 str 的想法是一个合理的开始。对于 set 对象,您需要先对条目进行排序,str(sorted(someset))。其他对象可能没有有用的__repr__或__str __(即它们可能只显示内存中的对象类型和位置)。总之,处理任意不可变的参数需要仔细考虑每个对象类型。