Navigation

This tutorial discusses some techniques of functional programming that
might be of interest to mathematicians or people who use Python for
scientific computation. We start off with a brief overview of
procedural and object-oriented programming, and then discuss
functional programming techniques. Along the way, we briefly review
Python’s built-in support for functional programming, including
filter,
lambda,
map and
reduce.
The tutorial concludes with some resources on detailed information on
functional programming using Python.

Python supports several styles of programming. You could program in
the procedural style by writing a program as a list of
instructions. Say you want to implement addition and multiplication
over the integers. A procedural program to do so would be as follows:

The Python module
operator
defines several common arithmetic and comparison operators as named
functions. Addition is defined in the built-in function
operator.add and multiplication is defined in
operator.mul. The above example can be worked through as
follows:

Another common style of programming is called object-oriented
programming. Think of an object as code that encapsulates both data
and functionalities. You could encapsulate integer addition and
multiplication as in the following object-oriented implementation:

Functional programming is yet another style of programming in which a
program is decomposed into various functions. The Python built-in
functions map, reduce and filter allow you to program in
the functional style. Note that in Python 3 (as compared to Python 2),
these functions have different behaviors, and reduce has been
removed: if you want to use reduce in Python 3, you must import it
from functools.

The function

map(func, seq1, seq2, ...)

takes a function func and one or more sequences, and apply
func to elements of those sequences. In particular, you end up
with a list like so:

[func(seq1[0], seq2[0], ...), func(seq1[1], seq2[1], ...), ...]

In many cases, using map allows you to express the logic of your
program in a concise manner without using list comprehension. For
example, say you have two lists of integers and you want to add them
element-wise. A list comprehension to accomplish this would be as
follows:

Things get more interesting once you combine map with the
lambda statement. As an exercise, you might try to write a simple
function that implements a constructive algorithm for the
Chinese Remainder Theorem.
You could use list comprehension together with map and
lambda as shown below. Here, the parameter A is a list of
integers and M is a list of moduli.

The function reduce takes a function of two arguments and apply
it to a given sequence to reduce that sequence to a single value. The
function
sum
is an example of a reduce function. The following sample code
uses reduce and the built-in function operator.add to add
together all integers in a given list. This is followed by using
sum to accomplish the same task:

In the following sample code, we consider a vector as a list of real
numbers. The
dot product
is then implemented using the functions operator.add and
operator.mul, in conjunction with the built-in Python functions
reduce and map. We then show how sum and map could be
combined to produce the same result.

The Python built-in function filter takes a function of one
argument and a sequence. It then returns a list of all those items
from the given sequence such that any item in the new list results in
the given function returning True. In a sense, you are filtering
out all items that satisfy some condition(s) defined in the given
function. For example, you could use filter to filter out all
primes between 1 and 50, inclusive.

For a given positive integer \(n\), the
Euler phi function
counts the number of integers \(a\), with \(1 \leq a \leq n\), such that
\(\gcd(a, n) = 1\). You could use list comprehension to obtain all such
\(a\)’s when \(n = 20\):

sage: [kforkinrange(1,21)ifgcd(k,20)==1][1, 3, 7, 9, 11, 13, 17, 19]

A functional approach is to use lambda to define a function that
determines whether or not a given integer is relatively prime
to 20. Then you could use filter instead of list comprehension
to obtain all the required \(a\)’s.

The function primroots defined below returns all primitive roots
modulo a given positive prime integer \(p\). It uses filter to
obtain a list of integers between \(1\) and \(p - 1\), inclusive, each
integer in the list being relatively prime to the order of the
multiplicative group \((\ZZ/p\ZZ)^{\ast}\).

This has been a rather short tutorial to functional programming
with Python. The Python standard documentation has a list of built-in
functions, many of which are useful in functional programming. For
example, you might want to read up on
all,
any,
max,
min, and
zip. The
Python module
operator
has numerous built-in arithmetic and comparison operators, each
operator being implemented as a function whose name reflects its
intended purpose. For arithmetic and comparison operations, it is
recommended that you consult the operator module to determine if
there is a built-in function that satisfies your requirement. The
module
itertools
has numerous built-in functions to efficiently process sequences of
items.