- 5.1 Function Definitions
- 5.2 Default Arguments
- 5.3 Variadic Arguments
- 5.4 Keyword Arguments
- 5.5 Variadic Keyword Arguments
- 5.6 Functions Accepting All Inputs
- 5.7 Positional-Only Arguments
- 5.8 Names, Documentation Strings, and Type Hints
- 5.9 Function Application and Parameter Passing
- 5.10 Return Values
- 5.11 Error Handling
- 5.12 Scoping Rules
- 5.13 Recursion
- 5.14 The lambda Expression
- 5.15 Higher-Order Functions
- 5.16 Argument Passing in Callback Functions
- 5.17 Returning Results from Callbacks
- 5.18 Decorators
- 5.19 Map, Filter, and Reduce
- 5.20 Function Introspection, Attributes, and Signatures
- 5.21 Environment Inspection
- 5.22 Dynamic Code Execution and Creation
- 5.23 Asynchronous Functions and await
- 5.24 Final Words: Thoughts on Functions and Composition
5.19 Map, Filter, and Reduce
Programmers familiar with functional languages often inquire about common list operations such as map, filter, and reduce. Much of this functionality is provided by list comprehensions and generator expressions. For example:
def square(x): return x * x nums = [1, 2, 3, 4, 5] squares = [ square(x) for x in nums ] # [1, 4, 9, 16, 25]
Technically, you don’t even need the short one-line function. You could write:
squares = [ x * x for x in nums ]
Filtering can also be performed with a list comprehension:
a = [ x for x in nums if x > 2 ] # [3, 4, 5]
If you use a generator expression, you’ll get a generator that produces the results incrementally through iteration. For example:
squares = (x*x for x in nums) # Creates a generator for n in squares: print(n)
Python provides a built-in map() function that is the same as mapping a function with a generator expression. For example, the above example could be written:
squares = map(lambda x: x*x, nums) for n in squares: print(n)
The built-in filter() function creates a generator that filters values:
for n in filter(lambda x: x > 2, nums): print(n)
If you want to accumulate or reduce values, you can use functools.reduce(). For example:
from functools import reduce total = reduce(lambda x, y: x + y, nums)
In its general form, reduce() accepts a two-argument function, an iterable, and an initial value. Here are a few examples:
nums = [1, 2, 3, 4, 5] total = reduce(lambda x, y: x + y, nums) # 15 product = reduce(lambda x, y: x * y, nums, 1) # 120 pairs = reduce(lambda x, y: (x, y), nums, None) # (((((None, 1), 2), 3), 4), 5)
reduce() accumulates values left-to-right on the supplied iterable. This is known as a left-fold operation. Here is pseudocode for reduce(func, items, initial):
def reduce(func, items, initial): result = initial for item in items: result = func(result, item) return result
Using reduce() in practice may be confusing. Moreover, common reduction operations such as sum(), min(), and max() are already built-in. Your code will be easier to follow (and likely run faster) if you use one of those instead of trying to implement common operations with reduce().