lru_cache for classmethod that depends on a class attribute (Python)

55 Views Asked by At

I have a Python classmethod Test.test(x) that produces expensive data, i.e. I would like to use functools.lru_cache as a wrapper. However, the output depends on a class attribute Test.a that can take a small number of different values. I would like to keep a cached version for each combination (a,x) of the attribute a and parameter x. I.e. I want the cache to work the usual way, as long as the attribute a is unchanged, but the method should be reevaluated once there is a change of the class attribute. How is this best achieved?

Here the code example:

from functools import lru_cache

class Test():
    a = 1

    def __new__(cls, a = 1):
        cls.a = a
        return super().__new__(cls)
    
    @classmethod
    @lru_cache(maxsize=32)
    def test(cls, x):
        return x * cls.a
    
print(Test.test(1),Test(2).test(1),Test.test(1))

Desired output (with lru_cache disabled): 1 2 2

Output with lru_cache: 1 1 1

Some clarifications:

  • The attribute a only gets changed rarely, hence it doesn't really matter whether there is a cached copy for each combination (a,x), or whether the cache is reset whenever the value of a changes.

  • The test method must be implemented that way as a classmethod (since it inherits from an abstract class which I cannot change).

  • Other ways to pass the value of a to the method are at least undesired. Test(a).test(x) would be the correct way in which similar functions of the project are called.

0

There are 0 best solutions below