Tree-recursive computational processes can often be made more efficient through memoization, a powerful technique for increasing the efficiency of recursive functions that repeat computation. A memoized function will store the return value for any arguments it has previously received. A second call to fib(25) would not re-compute the return value recursively, but instead return the existing one that has already been constructed.
    Memoization can be expressed naturally as a higher-order function, which can also be used as a decorator. The definition below creates a cache of previously computed results, indexed by the arguments from which they were computed. The use of a dictionary requires that the argument to the memoized function be immutable.

    1. >>> def memo(f):
    2. cache = {}
    3. def memoized(n):
    4. if n not in cache:
    5. cache[n] = f(n)
    6. return cache[n]
    7. return memoized

    If we apply memo to the recursive computation of Fibonacci numbers, a new pattern of computation evolves, depicted below.
    2.8.2   Memoization - 图1
    In this computation of fib(5), the results for fib(2) and fib(3) are reused when computing fib(4) on the right branch of the tree. As a result, much of the tree-recursive computation is not required at all.
    Using count, we can see that the fib function is actually only called once for each unique input to fib.

    1. >>> counted_fib = count(fib)
    2. >>> fib = memo(counted_fib)
    3. >>> fib(19)
    4. 4181
    5. >>> counted_fib.call_count
    6. 20
    7. >>> fib(34)
    8. 5702887
    9. >>> counted_fib.call_count
    10. 35