The functions used by map
,
filter
, reduce
and a
list
's sort
method can
also be a special function called a lambda form.
This permits us to use special one-use-only throw-away functions without
the overhead of a
def
statement. A lambda form is
like a defined function: it has parameters and computes a value. The
body of a lambda, however, can only be a single expression, limiting it
to relatively simple operations. If it gets complex, you'll have to
define a real function.
Generally, it's clearer to formally define a function rather than
try to define a lambda form.
We can play with lambda forms by applying them directly as
functions to arguments.
>>>
from math import pi
>>>
print (lambda x: pi*x*x)(5)
78.53981633970
This statement creates a
lambda
that accepts a
single argument, named
x
, and computes
pi*x*x
. This lambda is applied to an argument of 5. It
computes the area of a circle with a radius of 5.
Here's a lambda form used in the map function.
>>>
print map( lambda x: pi*x*x, range(8) )
[0.0, 3.1415926535897931, 12.566370614359172, 28.274333882308138,
50.26548245743669, 78.539816339744831, 113.09733552923255,
153.93804002589985]
This map
function applies our
radius-computing lambda form to the values from 0 to 7 as created by the
range
. The input sequence is mapped to the output
sequence by having the lambda function applied to each value.
Parameterizing a Lambda. Sometimes we have a lambda which -- in effect -- has two kinds
of parameters: parameters that are elements of a sequence being
processed by map
, filter
or
reduce
function, and parameters that are more
global than the items of a sequence.
Consider this more complex example.
spins = [ (23,"red"), (21,"red"), (0,"green"), (24,"black") ]
betOn= "black"
print filter( lambda x, y=betOn: y in x, spins )
betOn= "red"
print filter( lambda x, y=betOn: y in x, spins )
First, we create four sample spins of a roulette wheel, and save
this list
in a variable called
spins
. Then we chose a particular bet, saving this in
a variable called betOn
. If the given
betOn
keyword occurs in any of the
tuple
s that describe all of the spins, the
tuple
is kept.
The call to filter
has a lambda form that
uses a common Python hack. The filter
function only
passes a single argument value to the function or lambda form. If there
are additional parameters declared, they must have default values; in
this case, we set the default to the value of our variable,
betOn
.
Let's work through this in a little more detail.
As the filter
function executes, it
enumerates each element from the sequence, as if it had a
for
s
in spins
:
clause. Each
individual item is given to the
lambda
. The
lambda
then does the evaluation of y in
x
; x
is a tuple
from
the list
(e.g., (23, "red")) and
y
is a default parameter value, set to the value of
betOn
(e.g., "black"). Every time the
y
value actually appears in the
tuple
x
, ("black" in
(24,"black")
), the tuple
is selected to
create the resulting list
from the filter. When
the y
value is not in the
tuple
x
, the
tuple
ignored
This default parameter hack is required because of the way that
Python maintains only two execution contexts: local and global. The
lambda's execution takes place in a fresh local context with only its
two local parameter variables, x
and
y
; it doesn't have access to global variables. When
the lambda is created, the creation happens in the context where the
betOn
variable is known. So we provide the extra,
global parameters as defaults when the lambda is created.
As an alternative to creating list
s with
the filter
function, similar results can be created
with a list comprehension. This is covered just after the following
material on reduce
.