The preceding section introduced several functional-style features—list comprehensions, filtering and mapping. Here we demonstrate the built-in filter
and map
functions for filtering and mapping, respectively. We continue discussing reductions in which you process a collection of elements into a single value, such as their count, total, product, average, minimum or maximum.
filter
FunctionLet’s use built-in function filter
to obtain the odd values in numbers
:
In [1]: numbers = [10, 3, 7, 1, 9, 4, 2, 8, 5, 6]
In [2]: def is_odd(x):
...: """Returns True only if x is odd."""
...: return x % 2 != 0
...:
In [3]: list(filter(is_odd, numbers))
Out[3]: [3, 7, 1, 9, 5]
Like data, Python functions are objects that you can assign to variables, pass to other functions and return from functions. Functions that receive other functions as arguments are a functional-style capability called higher-order functions. For example, filter
’s first argument must be a function that receives one argument and returns True
if the value should be included in the result. The function is_odd
returns True
if its argument is odd. The filter
function calls is_odd
once for each value in its second argument’s iterable (numbers
). Higher-order functions may also return a function as a result.
Function filter
returns an iterator, so filter
’s results are not produced until you iterate through them. This is another example of lazy evaluation. In snippet [3]
, function list
iterates through the results and creates a list containing them. We can obtain the same results as above by using a list comprehension with an if
clause:
In [4]: [item for item in numbers if is_odd(item)]
Out[4]: [3, 7, 1, 9, 5]
lambda
Rather than a Function For simple functions like is_odd
that return
only a single expression’s value, you can use a lambda expression (or simply a lambda) to define the function inline where it’s needed—typically as it’s passed to another function:
In [5]: list(filter(lambda x: x % 2 != 0, numbers))
Out[5]: [3, 7, 1, 9, 5]
We pass filter
’s return value (an iterator) to function list
here to convert the results to a list and display them.
A lambda expression is an anonymous function—that is, a function without a name. In the filter
call
filter(lambda x: x % 2 != 0, numbers)
the first argument is the lambda
lambda x: x % 2 != 0
A lambda begins with the lambda
keyword followed by a comma-separated parameter list, a colon (:
) and an expression. In this case, the parameter list has one parameter named x
. A lambda
implicitly returns its expression’s value. So any simple function of the form
def function_name(parameter_list):
return expression
may be expressed as a more concise lambda
of the form
lambda parameter_list: expression
Let’s use built-in function map
with a lambda
to square each value in numbers
:
In [6]: numbers
Out[6]: [10, 3, 7, 1, 9, 4, 2, 8, 5, 6]
In [7]: list(map(lambda x: x ** 2, numbers))
Out[7]: [100, 9, 49, 1, 81, 16, 4, 64, 25, 36]
Function map
’s first argument is a function that receives one value and returns a new value—in this case, a lambda
that squares its argument. The second argument is an iterable of values to map. Function map
uses lazy evaluation. So, we pass to the list
function the iterator that map
returns. This enables us to iterate through and create a list of the mapped values. Here’s an equivalent list comprehension:
In [8]: [item ** 2 for item in numbers]
Out[8]: [100, 9, 49, 1, 81, 16, 4, 64, 25, 36]
filter
and map
You can combine the preceding filter
and map
operations as follows:
In [9]: list(map(lambda x: x ** 2,
...: filter(lambda x: x % 2 != 0, numbers)))
...:
Out[9]: [9, 49, 1, 81, 25]
There is a lot going on in snippet [9]
, so let’s take a closer look at it. First, filter
returns an iterable representing only the odd values of numbers
. Then map
returns an iterable representing the squares of the filtered values. Finally, list
uses map
’s iterable to create the list. You might prefer the following list comprehension to the preceding snippet:
In [10]: [x ** 2 for x in numbers if x % 2 != 0]
Out[10]: [9, 49, 1, 81, 25]
For each value of x
in numbers
, the expression x
**
2
is performed only if the condition x
%
2
!=
0
is True
.
sum
As you know reductions process a sequence’s elements into a single value. You’ve performed reductions with the built-in functions len
, sum
, min
and max
. You also can create custom reductions using the functools
module’s reduce
function. See https:/
for a code example. When we investigate big data and Hadoop (introduced briefly in Chapter 1), we’ll demonstrate MapReduce programming, which is based on the filter, map and reduce operations in functional-style programming.
(Fill-In)
_____, _____ and _____ are common operations used in functional-style programming.
Answer: Filter, map, reduce.
(Fill-In) A(n) _____ processes a sequence’s elements into a single value, such as their count, total or average.
Answer: reduction.
(IPython Session) Create a list called numbers
containing 1 through 15, then perform the following tasks:
Use the built-in function filter
with a lambda to select only numbers
’ even elements. Create a new list containing the result.
Use the built-in function map
with a lambda to square the values of numbers
’ elements. Create a new list containing the result.
Filter numbers
’ even elements, then map them to their squares. Create a new list containing the result.
Answer:
In [1]: numbers = list(range(1, 16))
In [2]: numbers
Out[2]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
In [3]: list(filter(lambda x: x % 2 == 0, numbers))
Out[3]: [2, 4, 6, 8, 10, 12, 14]
In [4]: list(map(lambda x: x ** 2, numbers))
Out[4]: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225]
In [5]: list(map(lambda x: x**2, filter(lambda x: x % 2 == 0, numbers)))
Out[5]: [4, 16, 36, 64, 100, 144, 196]
(IPython Session) Map a list of the three Fahrenheit temperatures 41, 32 and 212 to a list of tuples containing the Fahrenheit temperatures and their Celsius equivalents. Convert Fahrenheit temperatures to Celsius with the following formula:
Celsius = (Fahrenheit – 32) * (5 / 9)
Answer:
In [6]: fahrenheit = [41, 32, 212]
In [7]: list(map(lambda x: (x, (x - 32) * 5 / 9), fahrenheit))
Out[7]: [(41, 5.0), (32, 0.0), (212, 100.0)]
The lambda
’s expression—(x,
(x
-
32)
*
5
/
9)
—uses parentheses to create a tuple containing the original Fahrenheit temperature (x) and the corresponding Celsius temperature, as calculated by (x
-
32)
*
5
/
9
.
18.118.171.20