The Reduce Function in Python 3: Simply Explained

💡 The reduce() function from Python’s functools module aggregates an iterable to a single element. It repeatedly merges two iterable elements into a single one as defined in the function argument. By repeating this, only a single element will remain — the return value.

Minimal Example

Here’s the minimal example:

>>> from functools import reduce
>>> def my_sum(x, y):
	return x + y

>>> values = [1, 2, 3, 4]
>>> total = reduce(my_sum, values)
>>> total
10

The code performs the following steps:

  • Import the reduce function from the functools library.
  • Define the aggregator function my_sum.
  • Define a list of values.
  • Reduce values to a single value by passing it — along with the aggregator function my_sum — into the reduce function.
  • The result shows the sum of all values in the list.

Syntax

The reduce function takes three arguments:

reduce(function, iterable, initializer=None) 
ArgumentData TypeExplanation
functionCallable ObjectA function that takes two arguments and returns the aggregation of both values.
iterableIterable (e.g., list, tuple, set)An iterable to be aggregated into a single value.
initializerObjectAn optional initializer that serves as the initial value. If the initializer is given, the first aggregation happens between the initializer and the first iterable element. The default value is None.

The function argument defines how two values x and y are reduced to a single value (for example, lambda x, y: x + y). This way, we can iteratively reduce two values of an iterable (the second argument) to a single value—until only a single value is left in the iterable.

How to Write Python One-Liners with the Reduce Function

The following is drawn from my Python book “Python One-Liners”.


But before we move on, I’m excited to present you my new Python book Python One-Liners (Amazon Link).

If you like one-liners, you’ll LOVE the book. It’ll teach you everything there is to know about a single line of Python code. But it’s also an introduction to computer science, data science, machine learning, and algorithms. The universe in a single line of Python!

The book was released in 2020 with the world-class programming book publisher NoStarch Press (San Francisco).

Link: https://nostarch.com/pythononeliners


I thought I’d share it because recently I published an article about the fate of the reduce function in Python that got a lot of attention in the Python community. While the recently published article showcases the disadvantages of the reduce function, this article is really a love declaration. So enjoy studying the power of the reduce function to write concise Python one-liners.

In Python version 2, the reduce function was built-in so you could simply use it without importing any external library. However, Python’s creator Guido van Rossum pushed towards removing it in Python 3. In a now-famous article, he made his position clear: the reduce function is seldom used and doesn’t provide much value to the average Python coder. Therefore, in Python 3, you need to import it first from the functools library.

Anyways, a minority of Python experts still enjoys using the powerful reduce function in unexpected and beautiful ways. When researching this function as a preparation for this book, I realized that there exists a pop culture of “Python hackers” around the reduce() function and its unintended uses. And in fact, to create powerful Python one-liners, the reduce function is of invaluable help!

🧠 Repetition: The reduce function takes three arguments: reduce(function, iterable, initializer). The function argument defines how two values x and y are reduced to a single value (for example, lambda x, y: x + y). This way, we can iteratively reduce two values of an iterable (the second argument) to a single value—until only a single value is left in the iterable.

For example, calling reduce(lambda x, y: x + y, [0, 1, 2, 3]) performs the following computation: (((0+1)+2)+3)=6.

  • We first reduce the two values x=0 and y=1 to the sum x+y=0+1=1.
  • Then, we use this result of the first call of the lambda function as input to the second call of the lambda function: x=1 and y=2. The result is the sum x+y=1+2=3.
  • Finally, we use the result of this second call of the lambda function as input to the third call of the lambda function by setting x=3 and y=3. The result is the sum x+y=3+3=6.

In the last example, you have seen that the value x always carries the result of the previous (lambda) function. The argument x serves as the accumulated value while the argument y serves as the update value from the iterable. This is the intended behavior to iteratively “reduce” all values in the iterable argument to a single one. The optional third parameter initializer specifies the initial input for x.

💡 A lambda function is an anonymous function in Python. It starts with the keyword lambda, followed by a comma-separated list of zero or more arguments, followed by the colon and the return expression. For example, lambda x, y, z: x+y+z would calculate the sum of the three argument values x+y+z.

Reduce Function to Calculate Factorial

Let’s start by example—with a simple code puzzle you can solve.

from functools import reduce
print(reduce(lambda x, y: x * y, range(1, 6))) 

What is the output of this Python one-liner?

I gave this puzzle to 3,453 Python coders in my Finxter community. Six of them replied with the correct solution: The one-liner calculates the factorial function “5!”.

The result is

 (((((1 * 2) * 3) * 4) * 5) = 120

The reduce function iteratively combines two values from an iterable as specified in the first functional argument. In our case, the functional argument is an anonymous (lambda) function that takes two values, multiplies them, and returns the result.

Reduce Function to Expand List of List from List

Let’s keep exploring the reduce function further: what is the output of the following one-liner code puzzle? Let’s explore yesterday’s one-liner puzzle:

from functools import reduce
print(reduce(lambda x, y: x + [[z for z in range(y)]], [1, 2, 3, 4], [ ])) 

Yes, the solution is:

[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3]]

But how does this Python one-liner work?

You already know about the reduce function:

The reduce function iteratively combines two values from an iterable as specified in the first functional argument. In our case, the functional argument is an anonymous (lambda) function that takes two values x and y, combines them, and returns the result.

In the previous one-liner code puzzle, we combined the two (integer) values by multiplying them (and the result was the factorial function).

But in this puzzle, our two values x and y have a different data type. The third argument of the reduce function specifies the initial value of x. You can see that the initial value of x is an empty list.

However, value y still takes on each integer value of the list to be reduced (i.e., the second argument of the reduce function). So, we have y=1, y=2, y=3, and y=4.

Now, we repeatedly merge value y into the list x. Basically, we create a new list using list comprehension. The new list consists of all integer values up to y (exclusive).

This new list is then added to the old list (which was initially empty and is growing steadily).

Here is the exact procedure for each integer y in the list to be reduced:
(the right-hand side shows you how the new list is merged into the old list in each reduce step.)

 y=1:    [] + [[0]] = [[0]]
 y=2:    [[0]] + [[0,1]] = [[0], [0,1]]
 y=3:    [[0], [0,1]] + [[0,1,2]] = [[0], [0,1], [0,1,2]] 
 y=4:    [[0], [0,1], [0,1,2]] + [[0,1,2,3]] =  [[0], [0,1], [0,1,2], [0,1,2,3]]

Reduce Function to Calculate the Powerset

We’ll create a one-liner solution that calculates the powerset of a given set s:

# Dependencies
from functools import reduce


# The Data
s = {1, 2, 3}


# The One-Liner
ps = lambda s: reduce(lambda P, x: P + [subset | {x} for subset in P], s, [set()])


# The Result
print(ps(s))

Before we move on, guess the output of this code snippet!

The idea of this one-liner is to start the powerset as an empty set and repeatedly add subsets to it until no more subsets can be found.

Initially, the powerset contains only the empty set. In each step, we take one element x out of the dataset s and create new subsets that naturally emerge by adding x to all subsets that are already in the powerset. The size of the powerset therefore doubles each time we consider an additional element x from the dataset s. In this way, we can grow the powerset with n subsets one data set element at-a-time (but by n subsets at-a-time). Note that the powerset grows exponentially: for any new data set element x, we double the size of the powerset. This is an inherent property of powersets: they quickly overwhelm any storage capacity—even for relatively small datasets with only a few dozen of elements.

We use the reduce() function to maintain the current powerset in the variable P (which initially contains only the empty set). Using list comprehension, the reduce function creates new subsets – one for each existing subset – and adds them to the powerset P. In particular, it adds the value x from the dataset to each subset and thus doubles the size of the powerset (containing the subsets with and without the dataset element x). In this way, the reduce function repeatedly “merges” two elements: the powerset P and an element x from the dataset.

Hence, the result of the one-liner is the following:

# The Result
print(ps(s))
# [set(), {1}, {2}, {1, 2}, {3}, {1, 3}, {2, 3}, {1, 2, 3}]

This one-liner nicely demonstrates how important it is that you have a thorough understanding of the basics such as lambda functions, list comprehension, and set operations.

If you don’t have a lot of time to study Python for hours and hours, join my free “Coffee Break Python” email course. I will send you a daily Python lesson, cheat sheets. It’s fun (and 100% free)!

*** Yes, show me how I can participate! ***

Leave a Comment

Your email address will not be published. Required fields are marked *