Python快取:TypeError:无法散列的类型:'dict'

时间:2020-11-02 07:58:23

标签: python python-3.x

我正在尝试在Python中实现缓存功能。代码如下:

def memoize(func):
    """Store the results of the decorated function for fast lookup
    """

    # Store results in a dict that maps arguments to results
    cache = {}

    def wrapper(*args, **kwargs):
        # If these arguments haven't been seen before, call func() and store the result.
        if (args, kwargs) not in cache:        
            cache[(args, kwargs)] = func(*args, **kwargs)          
        return cache[(args, kwargs)]

    return wrapper

@memoize
def add(a, b):
    print('Sleeping...')
    return a + b

add(1, 2)

运行代码时,我得到TypeError: unhashable type: 'dict'

怎么了?

4 个答案:

答案 0 :(得分:2)

dict的密钥必须是可哈希的。您提供了不可散列的密钥(args,kwargs),因为kwargs是不可散列的dict

要解决此问题,您应该根据argskwargs的组合生成可哈希密钥。例如,您可以使用(假设argskwargs的所有值都是可哈希的)

key = ( args , tuple((kwargs.items())))

def memoize(func):
    """Store the results of the decorated function for fast lookup
    """

    # Store results in a dict that maps arguments to results
    cache = {}

    def wrapper(*args, **kwargs):
        # If these arguments haven't been seen before, call func() and store the result.
        key = ( args , tuple((kwargs.items())))
        if key not in cache:        
            cache[key] = cc = func(*args, **kwargs)          
            return cc
        return cache[key]

    return wrapper

@memoize
def add(a, b):
    print('Sleeping...')
    return a + b

print(add(1, 2))

答案 1 :(得分:1)

发生这种情况是因为您试图将字典作为键,这是一个问题。您可以使用frozenset()冻结字典,以便它

答案 2 :(得分:1)

在这一行:

cache[(args, kwargs)] = func(*args, **kwargs)

您使用kwargs作为密钥的一部分的dictdict是可变的,并且dict的键必须是不变的。

答案 3 :(得分:1)

Dict是不可哈希的,这意味着您不能在需要对象哈希的操作中使用它。将对象用作字典中的键是这些事情之一。

具体来说,奖励是一本字典,您正尝试将其用作另一本字典的键的一部分。

要使其生效,您应该创建一个函数来接收奖励并将其转换为数字或具有相同内容的任何字典的指纹字符串。

请注意,如果您将任何字典作为参数,无名或关键字进行传递,也会发生这种情况。如果您选择使用此解决方案,我的建议是在args和kwargs中都这样做,然后递归检查args中是否有字典。

作为第二点说明,在functools模块上,您具有lru_cache用于本地缓存,并且可以将cachetools用于缓存操作,将aiocache用于异步缓存,这些缓存支持除本地缓存以外的最受欢迎的后端。