【问题标题】:How to hash *args **kwargs for function cache?如何为函数缓存散列 *args **kwargs?
【发布时间】:2012-04-30 12:37:43
【问题描述】:

我正在使用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(value) 创建一个缓存键吗?泡菜?什么是最强大的?

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

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

【问题讨论】:

    标签: python


    【解决方案1】:

    这是 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__ (即它们可能仅显示对象类型和内存中的位置)。总之,处理任意不可散列的参数需要仔细考虑每种对象类型。

    【讨论】:

    • 以下是否也可以工作:key = (args, tuple(sorted(kwds.items())))?还是因为内部元组而变慢?
    • @max 是的,可以。是的,额外的指针会减慢它的速度并消耗更多的内存。
    • 也可以(args, frozenset(kwds.items()))
    • @Raymond is kwds.items() 假设是 kwargs.items() ?我没有看到任何地方定义的 kwds
    • 对于嵌套字典,考虑使用json.dumps(d, sort_keys=True) 来序列化字典(无论是args 还是kwargs) - source
    猜你喜欢
    • 1970-01-01
    • 2018-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-04
    • 2010-10-24
    • 2023-03-19
    • 1970-01-01
    相关资源
    最近更新 更多