why memoizing is faster

Terry Reedy tjreedy at udel.edu
Thu Mar 24 20:12:22 EDT 2011


On 3/24/2011 9:48 AM, Andrea Crotti wrote:
> I was showing a nice memoize decorator to a friend using the classic
> fibonacci problem.
>
> --8<---------------cut here---------------start------------->8---
>    def memoize(f, cache={}):
>        def g(*args, **kwargs):
>            # first must create a key to store the arguments called
>            # it's formed by the function pointer, *args and **kwargs
>            key = ( f, tuple(args), frozenset(kwargs.items()) )
>            # if the result is not there compute it, store and return it
>            if key not in cache:
>                cache[key] = f(*args, **kwargs)
>
>            return cache[key]
>
>        return g
>
>    # without the caching already for 100 it would be unfeasible
>    @memoize
>    def fib(n):
>        if n<= 1:
>            return 1
>        else:
>            return fib(n-1) + fib(n-2)

The irony of this is that memoizing 'recursive' functions with a 
decorator depends on the fact the Python does not have truly recursive 
functions. A function cannot call itself directly. It can only call 
whatever callable is bound externally to its definition name. Hence, 
memoize rebinds the definition name (in this case 'fib') to a wrapper, 
so that the function once known as 'fib' no longer calls itself but 
calls the wrapper instead.

If Python did what some have asked, which is to make 'recursive' 
functions actually recursive by replacing a local variable that matches 
the function name (in this 'fib') with a direct reference to the 
function itself, as a constant (and this could be done), then the 
wrapper would not get called from within the function.

-- 
Terry Jan Reedy




More information about the Python-list mailing list