@lru_缓存装饰器缓存未命中过多

2024-06-17 11:33:23 发布

您现在位置:Python中文网/ 问答频道 /正文

如何配置lru_cache根据接收到的实际值为其缓存设置密钥,而不是如何调用函数

>>> from functools import lru_cache
>>> @lru_cache
... def f(x=2):
...     print("reticulating splines...")
...     return x ** 2
...
>>> f()
reticulating splines...
4
>>> f(2)
reticulating splines...
4
>>> f(x=2)
reticulating splines...
4

换句话说,只有上面的第一个调用应该是缓存未命中,其他两个应该是缓存命中


Tags: fromimportcachereturndef密钥print调用函数
1条回答
网友
1楼 · 发布于 2024-06-17 11:33:23

要做到这一点,您必须经历将参数绑定到形式参数的过程。在C代码中实现的实际过程没有公共接口,但是在^{}中有一个(慢得多的)重新实现。这比通常使用functools.lru_cache慢约100倍:

import functools
import inspect

def mycache(f=None, /, **kwargs):
    def inner(f):
        sig = inspect.signature(f)
        f = functools.lru_cache(**kwargs)(f)
        @functools.wraps(f)
        def wrapper(*args, **kwargs):
            bound = sig.bind(*args, **kwargs)
            bound.apply_defaults()
            return f(*bound.args, **bound.kwargs)
        return wrapper
    if f:
        return inner(f)
    return inner

@mycache
def f(x):
    print("reticulating splines...")
    return x ** 2

如果该方法的性能损失太大,您可以改为使用以下技巧,这需要更多的代码复制,但运行速度要快得多,仅比通常使用lru_cache慢2倍左右(有时使用关键字参数时速度要快):

@functools.lru_cache
def _f(x):
    print("reticulating splines...")
    return x ** 2

def f(x=2):
    return _f(x)

这使用了更快的C级参数绑定来规范化对已记忆助手函数的调用,但需要复制函数的参数3次:一次在外部函数的签名中,一次在助手的签名中,一次在对助手的调用中

相关问题 更多 >