Python缓存:TypeError:不可哈希类型:'dict'

3

我正在尝试在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个回答

2
dict的关键字必须是可哈希的。由于kwargs是不可哈希的dict,所以您提供了一个不可哈希的关键字(args,kwargs)
要解决这个问题,您应该从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
这是因为您试图将字典作为键,这是一个问题。您可以使用frozenset()来冻结字典,以便它能够成功。

1

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

在您的特定情况下,奖项是一个字典,您正在尝试将其用作另一个字典的键的一部分。

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

顺便说一下,如果您以无名称或关键字形式传递任何dict,则也可能会发生这种情况。如果您选择采用此解决方案,我的建议是在args和kwargs中都执行此操作,并递归检查是否存在任何dict。

作为第二个附注,在functools模块上,您可以使用lru_cache进行本地缓存,还可以使用cachetools进行缓存操作,以及aiocache用于支持除本地缓存以外的最流行后端的异步缓存。


1
在这行中:

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

您使用 kwargs,它是 dict 的一部分作为键。dict 是可变的,而 dict 的键必须是不可变的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接