0

I need to make a decorator that checks if the function that its associated with was called before with exactly the same arguments as its being called with now. If it was, I need to return the previous output. If not I call it and store the result for future calls. Here is what I have:

class memoized(object):
    def __init__(self,f):
        self.__first=[]
        self.__last=[]
        self.__f=f
        self.__name__=f.__name__
        self.__value=[]
    def __call__(self,*args,**dargs):
        for i in self.__value:
            if(self.__first[i]==args and self.__last[i]==dargs):
                return self.__value[i]
        rv=self.__f(*args,**dargs)
        self.__first.append(args)
        self.__last.append(dargs)
        self.__value.append(rv)
        return rv

when I run it though it gives me an idex error. Im not sure why since theoretically the length of value first and last should be the same all the time because I append to all 3 of them. Any ideas?

Anatoliy Sokolov
  • 347
  • 1
  • 4
  • 10

1 Answers1

1

You append the return value to self.__value. Iterating over self.__value then gives you those return values, not indices into the list.

You could use zip() to pair up the 3 lists here instead:

for a, kw, rv in zip(self.__value, self.__first, self.__last):
    if(a==args and kw==dargs):
        return rv

You may as well append the positional and keyword arguments to the same list, as far as your implementation is concerned. There is little point in creating 3 separate lists here:

class memoized(object):
    def __init__(self,f):
        self.__cache = []
        self.__f = f
        self.__name__ = f.__name__
    def __call__(self,*args,**dargs):
        for a, kw, rv in self.__cache:
            if(a == args and kw == dargs):
                return rv
        rv = self.__f(*args, **dargs)
        self.__cache.append((args, dargs, rv))
        return rv

You may want to find a way to create a hashable key from the positional and keyword arguments instead, so you can use a dictionary to map from (a representation of) the arguments to the cached value. That avoids having to loop through all cache entries.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343