The Functools Module
Function tools
We looked at a number of higher-order functions in Chapter 5, Higher-order Functions.
These functions either accepted a function as an argument or returned a function (or
generator expression) as a result. All these higher-order functions had an essential
algorithm which was customized by injecting another function. Functions like max(),
min(), and sorted() accepted a key= function that customized their behavior.
Functions like map() and filter() accept a function and an iterable and apply
this function to the arguments. In the case of the map() function, the results of the
function are simply kept. In the case of the filter() function, the Boolean result of
the function is used to pass or reject values from the iterable.
All the functions in Chapter 5, Higher-order Functions are part of the Python
builtins package: they're available without the need to do an import. They are
ubiquitous because they are so universally useful. The functions in this chapter must
be introduced with an import because they're not quite so universally usable.
The reduce() function straddles this fence. It was originally built-in. After much
discussion, it was removed from the builtins package because of the possibility
of abuse. Some seemingly simple operations can perform remarkably poorly.
Memoizing previous results with lru_cache
The lru_cache decorator transforms a given function into a function that might
perform more quickly. The LRU means Least Recently Used: a finite pool of recently
used items is retained. Items not frequently used are discarded to keep the pool to a
bounded size.
Since this is a decorator, we can apply it to any function that might benefit from
caching previous results. We might use it as follows:
from functools import lru_cache
@lru_cache(128)
def fibc(n):
"""Fibonacci numbers with naive recursion and caching
fibc(20)
6765
fibc(1)
1
"""