简体   繁体   中英

How to use Python decorators so that a method uses functools.lru_cache andregisters itself?

I am decorating some methods in a class that accesses a datastore with lru_cache. I would like to apply another decorator, or to call lru_cache in another way, in order to add the caching method to a set the first time it is called. That way, when I know my datastore is dirty, I can clean the cache of each method. In other words, how do I build "register_data_reader" below? Or should I do it another way?

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()

Just a thought on how to implement this... Why even bother registering the methods with a decorator and tracking them in _cache_funcs ? Instead iterate over the classes methods and try to run .cache_clear() on them?


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())

Output:

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

Thanks Terry, that was useful.

In the end, I am running the following method in the init of my class, inspired by yours. It allowed me to bypass throwing an exception, and I'm registering once cached methods, as there are relatively few compared to the total number.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM