The Python 3 reduce()
function is a pre-defined function found in the functools
module. It accepts a function with two arguments and applies that function cumulatively to the items of an iterable.
In today’s post, we’ll discuss what the function does in depth. We’ll also talk about the difference between the Python 2 and Python 3 reduce()
function, and why this function may not be the best option to use in most cases. Last but not least, we’ll look at alternatives to the Python 3 reduce()
function.
Table of Contents
What does the reduce() function do?
As mentioned above, the Python 3 reduce()
function applies a function cumulatively to the items of an iterable.
It accepts three arguments – a function with two arguments, an iterable and an optional initializer.
Suppose we pass a function called myFunc()
(with two arguments) and a list called myList
to the reduce()
function, this is what the function does:
- First, it passes the first two elements in
myList
tomyFunc()
to generate a tentative result. - Next, it passes the tentative result and the third element in
myList
tomyFunc()
to update the tentative result. - It keeps repeating step 2 with the remaining items in
myList
until it reaches the end ofmyList
. - When that happens, it returns a single value as the final result.
Let’s look at some actual examples of how the Python 3 reduce()
function works.
Example 1: Finding the sum of numbers in a list
Example 1.1 Using named function
We can use the reduce()
function to find the sum of all numbers in a list.
from functools import reduce myList = [10, 12, 17, 42] def add2Numbers(a, b): return a+b total = reduce(add2Numbers, myList) print(total)
Here, we first import the reduce()
function using the import
statement on line 1.
Next, we declare and initialize a list called myList
.
On lines 5 and 6, we define a function called add2Numbers()
that accepts two arguments – a
and b
. This function returns the sum of a
and b
.
On line 8, we call the reduce()
function, passing the add2Numbers()
function and the myList
list to the function.
The reduce()
function does the following:
- It first passes the first two elements in
myList
to theadd2Numbers()
function. In other words, it passes the numbers 10 and 12 to theadd2Numbers()
function to get 22 as the tentative result. - Next, it passes the tentative result (22) and the third element in
myList
(17) to theadd2Numbers()
function again. This updates the tentative result to 39. - Finally, it passes 39 and the last element in
myList
(i.e. the number 42) to theadd2Numbers()
function to get 81 as the final result.
Once it reaches the last element in myList
, it returns the final result.
If you run the code above, you’ll get the following output:
81
Example 1.2 Using operator.add()
The example above shows how we can use the reduce()
function to cumulatively apply a user-defined function (add2Numbers
) to a list (myList
).
In addition to using the reduce()
function to apply a user-defined function, we can use it to apply a pre-defined function in Python.
An example is shown below:
from functools import reduce from operator import add myList = [10, 12, 17, 42] total = reduce(add, myList) print(total)
This example very similar to the previous example. The main difference is instead of passing the user-defined add2Numbers()
function to reduce()
, we pass the add()
function.
The add()
function is a pre-defined function available in the Python operator
module. It does the same thing as the add2Numbers()
function. In other words, it accepts two arguments and returns their sum.
Therefore, if you run the code above, you’ll get 81 as the output as well.
Example 1.3 Using lambda function
Besides passing user-defined or pre-defined functions, we can pass a lambda function to the reduce()
function.
The code below achieves the same result as the previous two examples:
from functools import reduce myList = [10, 12, 17, 42] total = reduce(lambda a, b: a+b, myList) print(total)
Here, we pass the following lambda function to the reduce()
function.
lambda a, b: a+b
If you are not familiar with lambda functions, you can check out the post here.
If you run the example above, you’ll get 81 as the output, similar to the previous two examples.
Example 2: Finding the smallest number in a list
Now that we’ve seen three variations of how we can use the reduce()
function to find the sum of numbers in a list, let’s look at another application of the reduce()
function.
In this example, we’ll use the reduce()
function to find the smallest number in a list.
This can be achieved with the code below:
from functools import reduce myList = [45, 2, 12, -3, 56] def getSmaller(a, b): if a < b: return a else: return b smallest = reduce(getSmaller, myList) print(smallest)
Here, the reduce()
function first passes 45 and 2 to the getSmaller()
function to compare the first two elements in myList
. This gives us 2 as the tentative result.
Next, the reduce()
function passes this tentative result (2) and the third element in myList
(12) to getSmaller()
to get the smaller number among the two. This gives us 2 as the result as well.
The function keeps comparing each tentative result with the next element in myList
until it reaches the end of the list.
If you run the code above, you’ll get the following output:
-3
Example 3: Using the reduce() function with an initializer
Besides passing a function and an iterable, we can pass a third optional argument to the reduce()
function. This argument is known as an initializer.
When the initializer is provided, the reduce()
function starts by passing the initializer and the first element in the iterable to the function.
Let’s look at an example:
from functools import reduce myList = [10, 12, 17, 42] def add2Numbers(a, b): return a + b total = reduce(add2Numbers, myList, 500) print(total)
Here, we pass 500 as the initializer to the reduce()
function.
The reduce()
function first passes 500 and 10 (the first element in myList
) to the add2Numbers()
function. This gives us 510 as the tentative result.
Next, the reduce()
function passes this tentative result (510) and the second element in myList
(12) to add2Numbers()
again to get 522 as the new tentative result.
It keeps doing that until it reaches the end of myList
.
If you run the code above, you’ll get
581
as the output.
Error Thrown by the reduce() function
The reduce()
function throws a TypeError
if you pass an empty iterable to it AND do not pass an initializer. For instance, if you run the code below,
from functools import reduce from operator import add # Empty list myList = [] # With initializer total = reduce(add, myList, 0) print(total) # Without initializer total = reduce(add, myList) print(total)
you’ll get the following output:
0 Traceback (most recent call last): File "...", line 12, in <module> total = reduce(add, myList) TypeError: reduce() of empty sequence with no initial value
When we call the reduce()
function with an empty list and an initializer (on line 8), it returns the initializer as the output (first line in the output above).
However, if you pass an empty list and do not provide the initializer, you get an error.
Difference between the Python 2 and Python 3 reduce() function
Now that we are familiar with how the reduce()
function works, let’s discuss the difference between the Python 2 and Python 3 reduce()
function.
The Python 2 reduce()
function is always available. In other words, to use the function, you do not need to import any module.
In contrast, in Python 3, the reduce()
function was moved to the functools
module. To use this function, you need to import the functools
module.
Criticism of the reduce() function
The reduce()
function has always been a controversial function.
The creator of Python Guido van Rossum personally stated that this is the function he hated the most. The main reason is the function makes our code less readable. It tends to complicate things unnecessarily as “99 percent of the time an explicit for loop is more readable.”.
For instance, in our Example 1 above, if we want to find the sum of numbers in a list, we can easily do it using a for
loop, as shown in the code below:
total = 0 myList = [10, 12, 17, 42] for i in myList: total += i print(total)
Or better still, we can use the built-in sum()
function in Python, as shown in the code below:
myList = [10, 12, 17, 42] total = sum(myList) print(total)
Both methods are easier to understand than the reduce()
function.
Therefore, unless there is a compelling reason to use the reduce()
function, you may want to use a loop instead.
Practice Question
Now that we’ve completed our discussion of the Python 3 reduce()
function, let’s move on to our practice question.
Today’s practice question is a bit different. You’ll be given a piece of code that uses the reduce()
function and your task is to rewrite the code using a loop.
Ready? Here goes.
Rewrite the following code using a loop:
from functools import reduce items = [112, 5122, 43, 644, 215, 9876] def myFunc(x, y): if x > y: return x - y else: return y - x result = reduce(myFunc, items) print(result)
The code above gives us 5768 as the output.
Suggested Solution
items = [112, 5122, 43, 644, 215, 9876] result = items[0] for i in items[1:]: if i > result: result = i - result else: result = result - i print(result)
Here, we first declare a variable called result
and initialize it to the first element in items
(line 2).
Next, we use a for
loop (lines 4 to 8) to iterate through the remaining elements in items
(i.e. items[1:]
).
Inside the for
loop, we compare each element with the tentative result (result
) and update result
accordingly based on whether the element is greater than result
. This is similar to what the myFunc()
function does in our practice question above.
Finally, we print the value of result
on line 10.
If you run the code above, you’ll get 5768 as the output.