[Tutor] a caching function and argument passing

Remco Gerlich scarblac@pino.selwerd.nl
Mon, 12 Jun 2000 11:26:37 +0200


On Mon, Jun 12, 2000 at 12:26:33AM -0700, Daniel Yoo wrote:
> After reading a little of Peter Norvig's "Paradigms of Artificial
> Intelligence", I've been playing around with equivalent programs in
> Python.  One of these include a "caching function generator", a general
> program that caches the results of another:
> 
> def makeCachedFn(fn):
>     cache = {}
>     def newfn(arg, fn=fn, cache=cache):
>         if not cache.has_key(arg):
>             cache[arg] = fn(arg)
>         return cache[arg]
>     return newfn
> 
> As you can see, this will cache f(x), and works pretty well.  For example:
> 
>   def factorial(x):
>     if x == 0: return 1
>     else: return x * factorial(x-1)
>   factorial = makeCachedFn(factorial)
>  
> does a very nice job in eliminating the cost of subsequent function
> calls.
> 
> The problem I'm running into is in trying to generalize the generator for
> functions with an arbitrary number of arguments.  I've tried to do
> something like:
> 
>   def newfun(*args, fn=fn, cache=cache)
> 
> but in Python 1.52, this is an illegal signature, since optional
> parameters go at the end.  I tried:
> 
>   def newfun(fn=fn, cache=cache, *args)
> 
> but that apparently doesn't work either, because default arguments have
> priority in getting assigned first.  Basically, I've been using the
> default arguments to simulate closures, but it's not quite working.
> 
> Any help on this would be greatly appreciated.  Thank you!

Here, I would make it into a class, default arguments can't do everything.
If you give a class a __call__ method, you can use its instances as
functions.

class makeCachedFn:
   def __init__(self, fn):
       self.fn = fn
	   self.cache = {}
   def __call__(self, *args):
       if not self.cache.has_key(args):
	       self.cache[args] = apply(self.fn, args)
	   return self.cache[args]

Now you can make __getitem__ too, and do for loops over the function :)
-- 
Remco Gerlich,  scarblac@pino.selwerd.nl