Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure lru_cache for class and static methods

I am trying to use lru_cache in Python3 to speed up common queries into our Salesforce database. Below is the relevant code that is supposed to

  • a) convert non-hashable arguments to hashable ones, and
  • b) enable the LRU cache for those objects.

When I try this code, the cache works for calling the functions with no arguments, but it doesn't seem to cache the function calls with arguments. Also, I am not sure of how to order the decorators for the decorated functions.

Note, I am using a class here with class and static methods so I can override the get and get_all methods for different subclasses of Resource.

Please explain what I am doing wrong or could be doing better.

from functools import lru_cache
from functools import wraps

class Resource(object):

    def hash_dict(func):
        """Transform mutable dictionnary
           Into immutable
           Useful to be compatible with cache
        """
        class HDict(dict):
            def __hash__(self):
                return hash(frozenset(self.items()))

        @wraps(func)
        def wrapped(*args, **kwargs):
            args = tuple([HDict(arg) if isinstance(arg, dict) else arg for arg in args])
            kwargs = {}
            for k, v in kwargs.items():
                if isinstance(v, dict):
                    kwargs[k] = HDict(v)
                elif isinstance(v, list):
                    kwargs[k] = tuple(v)
                else:
                    kwargs[k] = v
            return func(*args, **kwargs)
        return wrapped

    @staticmethod
    @hash_dict
    @lru_cache
    def get(cls, resource_id, lang='en', fields=None):
        pass

    @classmethod
    @hash_dict
    @lru_cache
    def get_all(cls, lang='en', filters=None, fields=None):
        pass
like image 561
Nicholas Tulach Avatar asked Oct 03 '17 12:10

Nicholas Tulach


People also ask

What does Functools lru_cache do?

Python's functools module comes with the @lru_cache decorator, which gives you the ability to cache the result of your functions using the Least Recently Used (LRU) strategy. This is a simple yet powerful technique that you can use to leverage the power of caching in your code.

Is lru_cache thread safe?

lru_cache decorator. lru_cache isn't ... It looks like a fantastic library that provides great functionality. But note that those classes are not thread-safe - you have to manually ......

How do you make a function static in Python?

To make a method a static method, add @staticmethod decorator before the method definition. The @staticmethod decorator is a built-in function decorator in Python to declare a method as a static method.

How do I invalidate LRU cache?

Clearing LRU Cache After the use of the cache, cache_clear() can be used for clearing or invalidating the cache.


1 Answers

No need for an additional package. The following work as expected:

import functools


class A:

  @staticmethod
  @functools.lru_cache(maxsize=None)
  def build(value):
    print('Creating', value)
    return A()


assert A.build('a') is A.build('a')
assert A.build('b') is A.build('b')
assert A.build('b') is not A.build('a')

Starting python 3.9, you can replace @functools.lru_cache(maxsize=None) by @functools.cache.

like image 181
Conchylicultor Avatar answered Oct 08 '22 00:10

Conchylicultor