1

Suppose that I have class A and this class has a method called function. Can I assign a cache as a property to this method? In the sense that I could call it like a property?

class A:
    def __init__(self,value):
        self.value=value
    def function(self,a):
        """function returns a+1 and caches the value for future calls."""
        cache=[]
        cache.append([a,a+1])
        return a+1;
a=A(12)
print a.function(12)
print a.function.cache

Which gives me the error:

AttributeError: 'function' object has no attribute 'cache'

I know it is possible to assign a cache to the main class but I am looking for a possible way of assigning it as a property to the method object.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Cupitor
  • 11,007
  • 19
  • 65
  • 91
  • Why do you want a method to have an arbitrary attribute and why do you want to do that to future readers of your code (who may be you)? – msw Jun 27 '13 at 16:43
  • @msw Because this method might do a very complex calculation and I might call it many times with same arguments. With this caching idea, I can instantly return its value without recalculating it. I think in enterprise applications you will often need such caching mechanism. – Cupitor Jun 27 '13 at 17:37
  • 2
    It is called [memoization](http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize), and there is a very well defined way to do it in Python. – msw Jun 27 '13 at 18:35

1 Answers1

1
class A:
    def __init__(self,value):
        self.value=value
        self.cache = {}
    def function(self,a):
        """function returns a+1 and caches the value for future calls."""

        # Add a default value of empty string to avoid key errors,
        # check if we already have the value cached
        if self.cache.get(a,''):
            return self.cache[a]
        else:
            result = a + 1
            self.cache[a] = result
            return result

As far as I know there is no way of having the cache as a property of the method. Python doesn't have such a feature. But I think perhaps this solution will satisfy your needs.

EDIT

Upon further research, there is indeed a way to do this in Python 3

class A:
    def __init__(self,value):
        self.value=value

    def function(self,a):
        """function returns a+1 and caches the value for future calls."""
        # Add a default value of empty string to avoid key errors,
        # check if we already have the value cached
        if self.function.cache.get(a,''):
            return self.function.cache[a]
        else:
            result = a + 1
            self.function.cache[a] = result
            return result
    function.cache = {}


a=A(12)
print(a.function(12))
print(a.function.cache)

This is because in Python 3 instance methods are just functions. BTW in Python 2 it is indeed possible to add attributes to functions, but not to instance methods. If you need to use Python 2 then there is a solution to your problem involving decorators that you should look into.

tatsuhirosatou
  • 25,149
  • 14
  • 39
  • 40
  • Kodus to van Rossum :D Then if I have three functions then I am basically screwed, cause in that case I have to assign caches by their name to functions manually!. – Cupitor Jun 27 '13 at 15:36
  • 1
    @Naji: Despite the fact that you've accepted this answer, a much better solution is to take the advice of msw and use the standard memoization techniques. Starting with Python 3.2, it could not be easier: just use the `@functools.lru_cache` decorator. But even in Python 2, it is not hard to do. Also, there is no need for the cache to be a property. You should never need to access the cache from outside the function being cached. The memoized function should handle all of that. – John Y Jun 27 '13 at 19:51