如何使用 Python 装饰器以便方法使用 functools.lru_cache 并自行注册?

Posted

技术标签:

【中文标题】如何使用 Python 装饰器以便方法使用 functools.lru_cache 并自行注册?【英文标题】:How to use Python decorators so that a method uses functools.lru_cache andregisters itself? 【发布时间】:2020-10-10 00:53:07 【问题描述】:

我正在使用 lru_cache 访问数据存储的类中装饰一些方法。我想应用另一个装饰器,或者以另一种方式调用 lru_cache,以便在第一次调用时将缓存方法添加到集合中。这样,当我知道我的数据存储是脏的时,我可以清理每个方法的缓存。换句话说,我如何在下面构建“register_data_reader”?还是我应该换一种方式?

from functools import lru_cache
class foo:

    _cached_funcs = set()

    @register_data_reader  # adds the LRU DECORATED func to _cached_funcs
    @lru_cache(maxsize=16)
    def reads_data_somewhere(self, ...)
        ...
        return data

    def clear_cache(self):
        for f in _cached_funcs:
            f.cache_clear()

【问题讨论】:

【参考方案1】:

只是想知道如何实现它...为什么还要费心用装饰器注册方法并在_cache_funcs 中跟踪它们?而是遍历类方法并尝试在它们上运行.cache_clear()


class Foo:

    @lru_cache(maxsize=16)
    def reads_data_somewhere(self):
        return 2 + 2

    def clear_cache(self):
        for method in dir(self):
            try:
                getattr(self, method).cache_clear()
            except AttributeError:
                pass


f = Foo()

print(f.reads_data_somewhere())
print(f.reads_data_somewhere())
print(f.reads_data_somewhere())
print(f.reads_data_somewhere())

print(f.reads_data_somewhere.cache_info())
f.clear_cache()
print(f.reads_data_somewhere.cache_info())

输出:

4
4
4
4
CacheInfo(hits=3, misses=1, maxsize=16, currsize=1)
CacheInfo(hits=0, misses=0, maxsize=16, currsize=0)

【讨论】:

【参考方案2】:

谢谢特里,这很有用。

最后,受您的启发,我在班级的 init 中运行以下方法。它允许我绕过抛出异常,并且我正在注册一次缓存的方法,因为与总数相比相对较少。

Class foo:

    ...

    def _register_cache(self):
        lst = dir(self)
        for method in lst:
            if hasattr(getattr(self, method), "cache_info"):
                self._cached_methods.add(method)

【讨论】:

以上是关于如何使用 Python 装饰器以便方法使用 functools.lru_cache 并自行注册?的主要内容,如果未能解决你的问题,请参考以下文章

python装饰器使用

Python装饰器详解

python3 如何给装饰器传递参数

Python高级--闭包与装饰器

在 Python 中,是不是可以使用相同的装饰器来装饰类和非类方法?

python3 装饰器