Functional programming in Python the simplest way

Anderson Resende
December 22, 2015
<p>One of the best ways to learn something is by comparing it to things we already know. This blog post has two main goals. The first one is to introduce the basic concepts of functional programming, and for that we will compare with the main rival paradigm, the imperative programming. The second is to show how to use functional programming in Python. For that, we will show some examples, and you may be surprised to see sometimes you use functional constructions without knowing.</p><p>The functional paradigm has its basis on the declarative aspect, which is ruled by two main constraints: the use of expressions and the lack of data mutation. The first one means that the code should tell what it aims to do instead of how to do it, and the second means that once a variable assumes a value it will never change on the course of the program execution. This contrasts with the imperative and object oriented paradigms, where we define statements and change variables (objects' state) on the course of the program.</p><p>Python is multi-paradigm language: it supports imperative, OO and functional programming paradigms. For the sake of simplicity, we will use the imperative paradigm to make our comparisons. Lets see some practical examples to compare the concepts we just learned (examples in Python 3):</p><h1 id="expressions-vs-statements-or-what-you-want-vs-how-to-do">Expressions vs. statements or "what you want" vs. "how to do"</h1><p>Lets say you want to sum all values in a list and print the result. You could do:</p><pre><code class="language-python">numbers = [1, 2, 3, 4] total = 0 for number in numbers: total += number print(total) </code></pre><p>In the code above we are telling the computer how to do the sum. We create the total variable then iterate over the list. At each lap we increment the total variable with one of the values in the list. And then we print the total. Now lets do the functional way:</p><pre><code class="language-python">numbers = [1, 2, 3, 4] print(sum(numbers)) </code></pre><p>This time we said: give me the sum of all numbers in the list. The code is clearer and more compact, or as we say: more declarative. You may say we’re cheating, because the sum function is already implemented. But we can do it also by using the <code>reduce</code> function, a basic one available in all functional languages:</p><pre><code class="language-python">import functools numbers = [1, 2, 3, 4] print(functools.reduce(lambda x, y: x + y, numbers)) </code></pre><p>reduce does basically <code>(((1+2)+3)+4)</code>. If you’re confused about how reduce works, Python docs <a href="https://docs.python.org/3/library/functools.html#functools.reduce">explain it well</a>.</p><h1 id="mutable-vs-immutable">Mutable vs. immutable</h1><p>Again, lets use the same example of calculating the total sum of values in a list. This time using an imperative style function:</p><pre><code class="language-python">def sum_lst(lst): total = 0 for number in lst: total += number return total </code></pre><p>As we can see, our function has only one variable called <code>total</code> that is updated on every iteration. This is clearly a case of a mutable variable. Now lets try a functional approach:</p><pre><code class="language-python">def sum_lst(lst): if not lst: return 0 else: return lst[0] + sum_lst(lst[1:]) # values are returned but no variable is changed </code></pre><p>This time we are not updating any variables and are using recursion, which is the functional programming way of doing loops.</p><h1 id="first-class-functions-higher-order-functions-and-lambda">First-class functions, Higher order functions and Lambda</h1><p>A programming language is said to have first-class functions when it supports passing functions as parameters, returning them or assigning them to variables. And higher order functions are functions that receive one or more function as arguments and return a function. Python supports <strong>first-class functions</strong>:</p><pre><code class="language-python">def call_my_name(name): print(name) call_my_name_again = call_my_name call_my_name('Anderson') # prints Anderson call_my_name_again('Anderson') # also prints Anderson </code></pre><p>And also <strong>higher order functions</strong>:</p><pre><code class="language-python">def convert_to(to_what, number): return to_what(number) convert_to(float, 20) # convert 20 to float convert_to(str, 10) # convert 10 to str </code></pre><p>Lets see another example: <code>map</code> is very popular higher order function that you've probably heard of before. It traverses an iterable and applies a function to it:</p><pre><code class="language-python">def double(number): return number * 2 print(list(map(double, [1, 2, 3, 4]))) </code></pre><p>Here is an imperative version of what is happening:</p><pre><code class="language-python">numbers = [1, 2, 3, 4] new_numbers = [] for number in numbers: new_numbers.append(number * 2) print(new_numbers) </code></pre><p>Moving on to <code>lambdas</code>. Lambdas are anonymous functions that are usually passed as parameters to other functions. Here is a Python example:</p><pre><code class="language-python">add_one = lambda number: number + 1 print(add_one(10)) # prints 11 </code></pre><p>Or using <code>map</code>:</p><pre><code class="language-python">print(list(map(lambda number: number + 1, [1, 2, 3, 4]))) </code></pre><p>Lambdas in Python can have only one line of code and automatically return the computed value, i.e, they are an expression, and so they don’t need the return statement.</p><h1 id="list-compressions">List Compressions</h1><p>Most times we use loops to iterate over lists and execute actions in its elements. List comprehensions are a more declarative way of doing that. Lets see an example. Here is a regular <code>for</code> iteration:</p><pre><code class="language-python">dogs = ["Todd", "Tom", "Bob"] big_dogs = [] for dog in dogs: big_dogs.append("Big {}".format(dog)) print(big_dogs) </code></pre><p>Now lets do the same but now using list comprehensions:</p><pre><code class="language-python">dogs = ["Todd", "Tom", "Bob"] big_dogs = ["Big {}".format(dog) for dog in dogs] print(big_dogs) </code></pre><h1 id="sum-up">Sum-up</h1><p>We introduced some functional programming concepts applying them using Python. Hopefully you can now identify functional constructions when you see one and also be able to use them when possible. Python has tons of other functional tools besides the ones showed in this post, start by looking for <a href="https://docs.python.org/3/library/functools.html">functools module</a>.</p>