December 5: Python Functional Programming Modules

A short entry for a change: As part of the Python Standard Library traversal, after yesterday's short post about Python's numeric and mathematical modules, I'm taking a look at itertools, functools and operator.

Highlights

  • There really are a lot of itertools functions.
  • functools contains a cached_property decorator.
  • I finally know what lru_cache does.
  • Apparently Python has a type of function overloading, by type of first argument, with singledispatch.
  • There are operator functions for performing in-place operations like +=.
  • operator.attrgetter can retrieve multiple and nested attributes.
  • operator.itemgetter can retrieve multiple items.

itertools

Do you like your iterators to be efficient and fast? itertools has your back then.

infinite

Some iterators are infinite: count() starts at an integer and just counts up, optionally by a step. cycle() cycles through a given sequence forever. repeat() repeats an item endlessly or n times.

finite

Among the terminating functions: accumulate() increasingly adds up the elements in the iterable. chain() collapses several iterables into a single one. compress() takes two iterables and returns only elements of the first iterable when the same index in the second iterable is True-ish. takewhile() gives you all of a sequence until the predicate fails and dropwhile() returns all of the sequence starting from the item where the predicate fails. filterfalse() inverts the filter function. groupby() groups an iterable by a given key or keyfunc. islice() gives you elements from an iterable, starting at start, optionally to stop, via step. tee() turns one iterable into n iterables. zip_longest works until the longest iterable is done and fills the others with a given filler value. starmap() is like map(), except that it passes an unpacked set to the function being mapped to.

combinatoric

Finally, there are combinatoric functions. product() combines all items of all iterables with one another. permutations() returns tuples of a given length, with all possible orderings and no repeated elements. combinations() returns tuples of a given length, already ordered with no repeated elements. combinations_with_replacements() includes repeated elements.

functools

functools contains functions that act on other functions. All the way down.

reduce() applies the given function cumulatively to the items of an iterable to reduce it to a single value.

singledispatch and singledispatchmethod give you a way to create overloaded functions, based on the type of the first argument to the function.

@wraps is a convenience function to create proper wrapping functions for decorators, adding the correct docstrings and so on.

caching

@cached_property creates a property that is evaluated only once, and on repeated access, the cached result is returned. Extremely useful for heavy computation in properties.

Similarly, @lru_cache wraps a function and retains results up to a memory limit. You can access cache information with cache_info(), returning hits, misses and maxsize. You can bypass the cache via __wrapped__ and clear it with cache_clear(). Use @cache if you want to use lru_cache with no maxsize (new in 3.9).

ordering

cmp_to_key takes a regular function useful for comparisons and transforms it into a function usable by key= interfaces like in sorted(). You use it like sorted(i, key=cmp_to_key(locale.strcoll)).

@total_ordering is a class decorator, that given a class that defines __eq__ and one comparison method, will add all the other comparison functions.

partials

partial takes a function and arguments, and returns a function (technically, a partial object) that will always be called with those arguments, plus additional ones, for example basetwo = partial(int, base=2). You can also use partialmethod() to do the same on classes.

operator

The operator module exposes functions corresponding to intrinsic Python operators, like operator.add() duplicating a+b behaviour. There is also a set of in-place operators, replacing operations like += – all of those just have an initial i, like iadd().

The probably most used functions are the attribute lookup functions – they are very useful as field extractors for functions like sorted() and groupby(). They include attrgetter (for nested and multiple attributes!), itemgetter and methodcaller.

The comparison functions are lt, le, eq, ne, ge, gt, not, truth, is_, is_not. The mathematical and logical functions are abs, add, and_, floordiv, index, invert, lshift, mod, mul, matmul, neg, or_, pos, pow, rshift, sub, truediv, xor. Functions for sequences are concat, contains, countOf and indexOf, getitem, setitem and delitem, plus length_hint.