'functools.lru_cache' 与 python 2 和 python 3 相比有何变化?

Any changes in 'functools.lru_cache' from python 2 and python 3?

我的代码在 python2.7 中工作正常,但在 python 3 中失败 functools.lru_cache(maxsize=32) 从 python 2 到 python 3 的任何变化。

我得到的错误是我的 configparser 对象在 functools.lru_cache 中缓存时它说

TypeError: unhashable type: 'ConfigParser'

想了解 'functools.lru_cache' 从 python 2 到 python 3 的变化吗?

#CONFI FILE
[translate]
api_url = https://url
api_version = version_num
api_key = key_value


#code goes here
import functools
from configparser import ConfigParser as SafeConfigParser
config = SafeConfigParser()
path ="./conf/services.ini"
config.read(path)


@functools.lru_cache(maxsize=32)
def build_api_params_key(config):
    """Build the api url and return with key."""
    api_url = config.get('translate', 'api_url')
    api_version = config.get('translate', 'api_version')
    api_key = config.get('translate', 'api_key')
    full_api_url = api_url + api_version

    return api_key

这里的问题不是functools.lru_cache,而是ConfigParser。 ConfigParser 继承自 RawConfigParser,后者在 Python 3x 中继承自 collections.abc.MutableMappingMutableMapping 抽象 class 不可散列,因为它是可变的并且没有实现 __hash__ 魔法方法。

由于 ConfigParser 实例不可哈希,因此它不能用作 functools.lru_cache 装饰器中缓存字典的键。

如需进一步参考,请参阅 this section of the configparser docs

假设有必要缓存配置文件的内容,另一种选择是读取文件的内容,然后将内容字符串传递给缓存的函数,就像这样

import functools
from configparser import ConfigParser as SafeConfigParser
path = "./conf/services.ini"
config_contents = open(path).read()

@functools.lru_cache(maxsize=32)
def build_api_params_key(config_contents: str):
    """Build the api url and return with key."""
    config = SafeConfigParser()
    config.read_string(config_contents)
    api_url = config.get('translate', 'api_url')
    api_version = config.get('translate', 'api_version')
    api_key = config.get('translate', 'api_key')
    full_api_url = api_url + api_version

    return api_key

在上面的解决方案中,读取配置文件以获取包含其内容的字符串。由于字符串是可哈希的,因此可以将其传递给缓存函数。如果您更愿意在函数内读取文件的内容,您也可以对文件指针执行类似的操作。但是,这些解决方案与 Python 2.7 不兼容,因为 read_string 未定义。