从内部函数禁用`functools.lru_cache`

Posted

技术标签:

【中文标题】从内部函数禁用`functools.lru_cache`【英文标题】:disable `functools.lru_cache` from inside function 【发布时间】:2019-10-25 21:55:11 【问题描述】:

我想要一个可以使用functools.lru_cache的函数,但不是默认的。我正在寻找一种方法来使用可用于禁用lru_cache 的函数参数。目前,我有两个版本的函数,一个有lru_cache,一个没有。然后我有另一个函数,它用一个参数包装这些函数,可以用来控制使用哪个函数

def _no_cache(foo):
    print('_no_cache')
    return 1


@lru_cache()
def _with_cache(foo):
    print('_with_cache')
    return 0


def cache(foo, use_cache=False):
    if use_cache:
        return _with_cache(foo)
    return _no_cache(foo)

有没有更简单的方法来做到这一点?

【问题讨论】:

你不能在函数的内部处理它——如果它是缓存命中,函数甚至不会被调用。 所有你可以在这里正确地发明 - 只是一个工厂函数,它将返回缓存或未缓存的函数对象(取决于参数),而不是函数结果 RomanPerekhest 为什么我要返回函数对象而不是函数结果? @TheStrangeQuark,生成对象的场景有很多种。没有人强迫您扩展“家庭”代码,这取决于您 【参考方案1】:

您不能从装饰函数内部禁用缓存。但是,您可以通过__wrapped__ 属性直接访问该函数来稍微简化代码。

来自documentation:

原始底层函数可通过__wrapped__ 访问 属性。这对于自省,绕过缓存很有用, 或者用不同的缓存重新包装函数。

演示:

from functools import lru_cache

@lru_cache()
def f(arg):
    print(f"called with arg")
    return arg    

def call(arg, use_cache=False):
    if use_cache:
        return f(arg)
    return f.__wrapped__(arg)

call(1)
call(1, True)
call(2, True)
call(1, True)

输出:

called with 1
called with 1
called with 2

【讨论】:

【参考方案2】:

为了检查,你可以使用cache_info()包装函数的方法:

from functools import lru_cache

@lru_cache()
def my_function(foo):
    return foo * 2

def cache(foo, use_cache=False):
    if use_cache is False:
        return my_function.__wrapped__(foo)
    return my_function(foo)

print(cache(10, use_cache=True))    # cache miss
print(cache(10, use_cache=True))    # cache hit
print(cache(10, use_cache=False))   # bypass
print(cache(20, use_cache=False))   # bypass

print(my_function.cache_info())     # cache size=1, hit=1, miss=1

打印:

20
20
20
40
CacheInfo(hits=1, misses=1, maxsize=128, currsize=1)

【讨论】:

以上是关于从内部函数禁用`functools.lru_cache`的主要内容,如果未能解决你的问题,请参考以下文章

CSS3 Snow Fall Animation 禁用内部链接

因bug禁用内部IP导致链路不通,阿里云大面积瘫痪!Intel处理器又曝漏洞;Tomcat 9.0.10发布

AutoCompleteTextView - 禁用过滤

如何从Objective-C中的异步内部函数内部返回外部函数

如何从Objective-C中的异步内部函数内部返回外部函数

iOS 禁用内部版本或平台(iTunes 连接)