Python reduce(): The Complete Guide (With Examples)

These days, organizations are collecting far more data than they’ll ever get a chance to analyze. The blessing of big data for deep insights comes hand in hand with the curse of wading through piles of information that need summarizing. Your Python collection may straight up look like an episode of Hoarders. If you’re feeling an overwhelming urge to aggregate and declutter, Python’s reduce() might just be the function for you.
We’re breaking down reduce() in this article: what it is, how it works, and plenty of examples for thorough understanding. If you’re new to the map(), filter(), reduce() trifecta, we’ll explain how these three relate to functional programming. We’ll also cover when to use and when to avoid the reduce() function in favor of other Pythonic options.
What is the reduce() Function in Python?
Python’s reduce() function repeatedly combines elements from an iterable to produce a single value. It comes from the functools module, which is part of Python’s standard library. You’ll find reduce() most helpful when you need to carry out the same action across an entire collection of values. While the final result is often a single number, it may be any object including a string, list, or dictionary. Python includes dedicated functions or methods for many of the actions reduce() typically performs (such as sum(), min(), max(), str.join(), etc.), so it appears less frequently in Python than many other programming languages.
How reduce() Works
reduce() requires two arguments: a function and an iterable. That function argument may be a user-defined function or a lambda function. reduce() processes items from left to right across the iterable by applying the function in a cumulative manner. The function itself should also accept two arguments: the accumulated result so far and the current element. Each time the function is called, its return value becomes the updated accumulated result, and reduce() continues in this manner until it has processed all the elements in your iterable.
Here’s a simple example to get the hang of things. The reduce() function cumulatively works its way through the items in the list, repeatedly adding each one to a running total until it arrives at a final sum of all the values in the list.
reduce(add, [1, 2, 3, 4])
reduce() processes these from the starting value 1 and adding each other value one by one:
1 + 2 → 3
3 + 3 → 6
6 + 4 → 10
After exhausting the list, it returns 10, the total sum.
Here, add represents a custom function that takes in two values and returns their sum. We’ll show you how to write this function, both as a named function and a lambda function, in the next section.
Practical reduce() Examples
Now that you know what Python’s reduce() is and how it generally works, let’s dive into several practical demonstrations of the reduce() function in Python. Notice how reduce() requires two arguments throughout.
Summing Values with reduce()
Let’s return to our example of summing numeric values in a list. From functools, import reduce(). Then you can define add() as follows:
With each call to the add() function, the two input values are summed. reduce() uses the result together with the next list element as the inputs to add() in its next call until it cycles through all values and is left with a single cumulative value. Also notice that we pass the function name, add, without parentheses. This lets reduce() call the function repeatedly, providing the arguments according to its reduction process.
Finding the Minimum and Maximum Values
You may also use the reduce() function to find the minimum and maximum values in a list. This code utilizes two separate named functions and calls to reduce() to find both:
Although reduce() can find minimum and maximum values, Python’s built-in min() and max() functions lead to much simpler, easy-to-read code. We’ll come back to this point in a later section about when to avoid the reduce() function.
Getting the Maximum Value with a Custom Comparison
Remember that the reduce() function isn’t just for numerical values. You may compare strings, dictionary items, individual lists, or nearly any Python object. The iterable, too, doesn’t necessarily need to be a list. It just needs to be an iterable object that Python can process one item at a time.
Let’s now use reduce() to find the longest string in a tuple. In each call, reduce() compares the length of two strings and keeps whichever one has more characters. It continues doing this until only the longest string remains.
In this case, the “maximum” is not a number but the longest string. Python’s built-in max() function can also handle this type of problem via its key argument, but reduce() does offer a straightforward way to understand how we can apply repeated comparisons to identify the maximum element.
Using Lambda Functions in reduce()
You’ve seen reduce() paired with user-defined functions so far, but you’ll commonly see lambda functions in reduce() as well. Lambda functions are small, anonymous functions that you’ll often only use once in your code. They can save you a bit on typing, but should be quite simple in nature to avoid confusion.
Here’s our initial summing values example rewritten with a lambda function instead of a named one:
Note that we pass the lambda directly to reduce(), just as we passed add without parentheses in the earlier example. The first parameter in the lambda expression, x, represents the accumulated result, while y represents the current list item. We achieve the same result with either the lambda function or the named function approach; the choice between the two options merely comes down to code preference and readability.
Including an Initializer
reduce() requires two arguments: the function used for accumulation and the iterable, but the reduce() function takes an optional third argument for an initializer: reduce(function, iterable, initializer). When you call reduce(), the default behavior uses the first element of the iterable as the starting value. You may start from a different value, however, through the initializer argument. The initializer then becomes the first accumulated value before reduce() applies the function to the iterable.
The initializer proves especially handy when you need the accumulation to begin from a specific starting value or when handling empty iterables. Passing an empty list as the iterable to our summing example yields an error without an initializer since there is no first element to use as the initial accumulated value. We can instead begin our total with a starting value of 0 to avoid issues:
reduce() Behind the Scenes
Now that you’ve gotten a feel for what the reduce() function can do, it’s worth understanding a few Python concepts to explain reduce()’s behavior and association with functional programming.
What is a Higher-Order Function?
A higher-order function accepts a function as an input, returns a function as an output, or both. Python’s reduce() is an example of a higher-order function because it takes in a function as its first argument. The related functions map() and filter() are also higher-order. Even built-in functions such as max() and sorted() qualify as higher-order functions since they accept a function through their optional key argument.
Callable Objects and reduce()
reduce()’s first argument must be a callable object, which is anything that can be called with parentheses. Examples of callables include:
Named functions
Lambda functions
Built-in functions
Objects with a
__call__()method
You’ll typically see functions occupying this first position, but advanced users can also pass instances of custom classes defined with a __call__() method.
reduce() in Functional Programming
Functional programming is a programming style that treats functions as first-class objects. It commonly uses small functions together to manipulate data. Functional programming relies heavily on the higher-order map(), filter(), reduce() functions to transform, filter, and aggregate data, respectively. While Python does support functional programming, it’s not a purely functional language. Many developers tend to mix functional and imperative styles to write clear, efficient code and keep their Python skills sharp.
reduce() was moved to Python’s functools module in Python 3 because it was used less frequently than many other built-in functions. You will still find map() and filter() in Python’s core codebase.
When to Avoid reduce()
While reduce() is a powerful higher-order function and important to functional programming, it often isn’t the most readable solution. We’ll cover a few important places you may choose other approaches instead of reduce() in this section.
reduce() versus Built-in Functions
Since Python 3, you’ll need a from functools import reduce to kick things off because many of reduce()’s common use cases are handled more cleanly by built-in functions. For example, consider the summing example we’ve explored previously. The built-in sum() function in Python totals up lists and other iterables with easier-to-read code:
Likewise, min() and max() find minimum and maximum values more directly, and they also work with many non-numeric data types. As a general rule of thumb, rely on Python’s built-in functions instead of reduce() whenever they express your intent more clearly.
Alternatives: List Comprehensions, Loops, itertools.accumulate()
When it comes to Python, reduce() isn’t the only way to process iterable data. Here’s a brief look into some related alternatives.
List comprehensions offer a powerful way to transform or filter data; however, they produce another iterable rather than reducing to a single value. As a result, list comprehensions more commonly take the place of the map() function or the filter() function instead of reduce().
You will also encounter for loops when processing iterables. These prove helpful when implementing more complex logic such as multiple conditional statements or several accumulation steps. for loops may also result in a single cumulative value, and they are often easier to debug than reduce(). They may also be easier to modify should you require additional intermediate steps.
The accumulate() function in Python lives in the itertools module. It also operates across iterables in a cumulative fashion, but instead of returning a single value like reduce(), it gives you every accumulated value. This proves especially useful for running totals, cumulative products, etc. and can help you check that your function appropriately accumulates values.
The following code demonstrates itertools.accumulate() with the same iterable and same function for the callable as our summing example:
Unlike reduce(), accumulate() expects the iterable as its first argument and accepts the accumulation function as an optional second argument. It returns an iterator of accumulated values, which you may consume by converting it to a list.
Like most topics in Python, the best solution depends on your specific task. Prioritize readability over forcing a functional programming style, especially since Python supports many different programming paradigms.
Data Science Use Cases
Data scientists routinely rely on the pandas and NumPy libraries to handle data, and you won’t typically see reduce() used alongside either of those libraries because they have aggregation methods of their own. You will, however, notice reduce() in data science problems when repeatedly combining more complex objects.
A More Complex Example with Data Structures
Beyond numbers and text, reduce() can also merge more complex objects like dictionaries. Say you have a list of dictionaries that records daily website page views. If you’d like to combine that list into a single dictionary to analyze the total views to each page, you can use reduce() in code such as the following:
This routine processes each daily dictionary, and the reduce() function cumulatively combines total page views into a master dictionary by adding counts for matching pages. If a page doesn’t appear in a daily dictionary, .get() returns zero instead of raising an error. We also begin from an empty dictionary as our initializer in case daily_views is an empty list.
Although built-in aggregation functions cover many common tasks, reduce() remains a powerful tool for data science when you need to combine more complex data structures into a single result repeatedly.
Common Pitfalls
Despite its usefulness, the reduce() function also comes with a few common “gotchas” for you to be aware of. Review these top pitfalls to avoid issues in your Python code.
Missing Initializer
reduce() starts accumulating from the first value in your iterable if you don’t supply an initializer value. This means you should pass an initializer whenever the iterable might be empty; otherwise, you won’t have a default value to start with, and you’ll get a TypeError.
This example illustrates the issue using an empty generator and no initializer starting value:
To fix the issue, provide an initializer so the reduce() function has a starting value even when the iterable is empty:
Returning the Wrong Value from the Callable
The callable function you pass to reduce() must return the accumulated value after each call. The reduce() function uses this return as the accumulator for its next iteration.
While this requirement seems straightforward, it’s easy to violate in practice. In the data science page views examples, the following callable does not work because the .update() method modifies dictionaries in place and returns None:
lambda x, y: x.update(y)
Whether you use a named function or a lambda function, make sure it returns the updated accumulated value; otherwise, reduce() won’t have the right accumulator when processing the next value.
Wrapping Up
The Python reduce() function combines elements from an iterable into a single value. You’ll find it in Python’s functools module, and its general syntax follows reduce(function, iterable, initializer), where initializer is an optional third argument for an initial value. reduce() proves most helpful when repeatedly incorporating values into one result, especially for multiplying numeric values and doing complex aggregation tasks such as merging dictionaries.
Although other functions in Python often provide more readable solutions for common tasks like summing values or finding maximums and minimums, the reduce() function remains a valuable higher-order function for custom accumulation logic.
Learn more about when to use reduce() in your code by interacting with the AI Tutor. This prompt will help kick things off:
- Master Python Filter: Syntax, Examples, and Best Practices
- Python Max Int: Understanding Arbitrary Precision Integers
- Python KeyError Exceptions: Causes and Fixes Explained
- Python Null (None): Guide to Missing Values and NoneType
- Python Backend Development: Build Your First API
- Python Backend Frameworks: How to Choose the Right One
- Python Return Multiple Values: 4 Methods & Examples
- Python Multiline Strings: The Complete Guide
- Python not Operator: The Complete Guide to Logical Negation
- Python Print New Line: Methods, Examples, and Best Practices
Kimberly Fessel