Functional Programming
In the last year, I have spent much more time writing Javascript than any other language. Javascript uses a lot of functional programming. That means that when you call a function, the return value for that function is passed directly into the next function. Furthermore, the operation doesn't use scope outside of the current function, inputs, and outputs.
For example, you may see this:
anyArrayOfValues.map(item => ...).filter(item => ).reduce(itemA, itemB)
First, we call the map function, and an array is returned. Then, we immediately call the filter function on that returned array—thus returning another array. Finally, the array is reduced to the end return value.
Functional programming is a paradigm. There are no strict rules for how it exists and is used in different languages.
This is especially true for Python. Python is a general-purpose programming language ("There are no rules!"). We can use object-oriented programming, functional programming, procedural programming, or combinations of each method.
In this article, we are going to discuss what the built-in functions map()
, filter()
, and reduce()
do, and give examples on how to use them.
map()
The map
function takes two arguments:
- A function that is called on each item in the list
- List
It returns an iterator (not a list) object. Then, to get the values, we can wrap the map object in the list()
constructor.
Let's see how this works.
>>> exampleList = [1, 2, 3, 4, 5, 6]
>>> def power_of_2(num):
return num ** 2
First, we define a list and create a function that accepts the item (num
). Then, we raise that number to the power of two and return the result.
>>> map(power_of_2, exampleList)
<map object at 0x7f9835943df0>
>>> mapObj = map(power_of_2, exampleList)
>>> list(mapObj)
[1, 4, 9, 16, 25, 36]
Next, we can do a test run where we pass the function and list into the global map
function. The return value is a map object
.
We do the same thing but place the map object
into a variable.
Finally, we place the variable into the list()
constructor to reveal the new values. Notice that the item is implicitly passed into the function.
filter()
What's nice about these three functions is they all work in a similar way. The filter
function also takes a function as its first argument and a list as its second.
Unlike map
, which expects any function to be applied, the function that we pass into filter
needs to evaluate to either a boolean value when it's applied to each item in the list.
Let's explore the function.
>>> def true(num):
return True
>>> mapObject = filter(true, exampleList)
>>> list(mapObject)
[1, 2, 3, 4, 5, 6]
In the example above, we created a function that automatically returns True
. Therefore, every number makes it through the filter.
Now, let's create a function that actually evaluates to either True
or False
. It will try to find all the even numbers.
>>> def findEven(num):
return (num % 2) != 1
>>> mapObject = filter(findEven, exampleList)
>>> list(mapObject)
[2, 4, 6]
Again, we saved the map object
into the mapObject
variable and passed it into the list()
constructor to see the results.
reduce()
The reduce()
function is not a global function like the other two in this article. Instead, it has to be imported from functools
.
I believe this is because using the reduce
function is considered hard to read. Regardless, we are going to explain how to use it.
The reduce
function takes the values in a list and reduces them down to one value. It's an unoriginal example but with our list, this is pretty straightforward. We can take each value and add it to the next.
>>> def add(num1, num2):
return num1 + num2
>>> from functools import reduce
>>> reduce(add, exampleList)
21
We don't have to pass the returned value into the list()
constructor because we no longer have a list!
Putting Them All Together
We combine all of these functions by passing them into one another.
>>> reduce(add, filter(findEven, map(power_of_2, exampleList)))
56
You wouldn't be alone if you thought this was hard to read! It's not very Pythonic. Because it is difficult to read. Therefore, it's probably better not to do this.
However, working through how this statement works can help you understand the three functions. Thanks for reading!