[Tutor] can someone explain to me Lambda functions/statements, preferably with examples, I don't get it

Daniel Yoo dyoo@hkn.EECS.Berkeley.EDU
Wed, 23 Aug 2000 02:02:12 -0700 (PDT)


> can someone explain to me Lambda functions/statements, preferably with
> examples, I don't get it, I don't understand how to use them either

I'll try, but this message will be slightly long to give a good
explaination.


lambda allows you to make on-the-fly functions.  This only makes sense
once you see that functions, like data, can be passed around.  I'll need
to take a slight detour for this.  Say that we had the following list:


###
>>> l = range(20)
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
###


Let's say that I'd like to get a new list, with only the even numbers.  We
could do this:


###
>>> def onlyEvens(L):
...     result = []
...     for x in L:    
...         if (x % 2 == 0):
...             result.append(x)
...     return result
...  
>>> onlyEvens(l)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
###


What if we wanted to change this so it only gave us back the odds?  Well,
we could do cut-and-paste:


###
def onlyOdds(L):
     result = []
     for x in L:    
         if (x % 2 == 1):
             result.append(x)
     return result
###


This isn't bad.  However, what programmers often do is try to generalize
things.  In those two functions, we're looking at every element in a list,
and doing some sort of check.  We could write these tests out simply as:

    def isEven(x): return (x % 2 == 0)
    def isOdd(x): return (x % 2 == 1)

onlyEvens(), then, will look like this:


###
def onlyEvens(L):
     result = []
     for x in L:    
         if isEven(x):
             result.append(x)
     return result
###


and onlyOdds() will be one line different.


Now here's the jump --- why not allow the program to send not only the
list, but the criterion for knowing which items to keep?  Why can't we
write something like:


###
def myfilter(f, L):
     result = []
     for x in L:    
         if f(x):
             result.append(x)
     return result
###


It turns out that this works.  Functions can be passed around, just like
lists and strings and ints.  Now that we know we can write myfilter, then
to get all the odd numbers, we'd just need to do this:


###
>>> myfilter(isOdd, l)
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
>>> myfilter(isEven, l)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
###


No messiness involved.  And very reusable.

So now we have something that will filter out items from a list.  This is
actually really powerful, since this suddenly gives us amazing power over
lists, and not just lists of integers.  Take a look:

###
>>> import string
>>> def isLowercase(x): return string.lower(x) == x
>>> myfilter(isLowercase, ['This', 'is', 'A', 'tEst', 'of', 'the',
'emergency', 'Broadcast', 'systeM'])
['is', 'of', 'the', 'emergency']
###


To get back to the original question, lambda is used when you want to pass
a function to one of these function-eating functions.  Heck, this might be
a one-shot thing that you're doing.  In this case, you can do something
like:


###
>>> myfilter(lambda x: 't' in x, ['This', 'is', 'A', 'tEst', 'of', 'the',
'emergency', 'Broadcast', 'systeM'])
['tEst', 'the', 'Broadcast', 'systeM']
###


which pulls out all the words that have the letter 't' in them.  I could
have written 'containsTheLowercaseLetterT()' as a separate function.  
This is an example where the lambda stuff comes in handy --- it's short,
it's quick, and you don't need to type so much.

The problem is that it's localized --- if you find yourself retyping the
same lambda over, then it must be so generally useful that you should
grant it the life of a real function.  Also, lambdas are also limited to a
single expression.  This really limits them to simple tests.


Finally, Python already gives you a bunch of built-ins that do things to
lists.  It does have a 'filter()' command.  Furthermore, it has 'map()',
which is even more impressive:

###
>>> map(lambda x: x + x, ['i', 'will', 'be', 'double', 'talking'])
['ii', 'willwill', 'bebe', 'doubledouble', 'talkingtalking']
###

Play around with it; you'll have fun.  *grin*  I hope this helps.