Python's syntax is relatively convenient and easy to work with, but aside from the basic structure of the language Python is also sprinkled with small syntax structures that make certain tasks especially convenient. The lambda
keyword/function construct is one of these, where the creators call it "syntactical candy". Here we'll examine how to use them.
To understand the lambda
keyword/function and their constructs we must first review how regular function definitions work in Python. The following is the basic structure of a function definition:
[python]
def basic(arg):
# Or whatever the function does
pass
# Or whatever the function returns
return arg
[/python]
What we've defined here is essentially an empty function named basic, which receives one argument, does nothing (the pass statement is essentially a valid "do nothing" statement), and then returns the argument it was given. This is the most basic structure of most functions, but the simplest function definition would only include one of these statements - in one statement it would either do something (or pass), or return something or None
(a return
statement always returns at least the None
instance, so it can't actually return nothing). Here is how these two cases would look:
[python]
def simple1(arg): pass
def simple2(arg): return arg
[/python]
Notice how we also saved a line by putting the function body statements on the same line as the definition statement. A lambda
function structure is exactly the latter of these two structures, i.e. a one-statement function which returns something, the difference being that the "return" keyword is implied and doesn't show up in the construct. Now that we know how lambda
functions work (identically to a one-statement function), let's construct the simple2 function in lambda
form. To do this, we simply use the lambda
construct - if we call our lambda
function simplest, it would be like so:
[python]
simplest = lambda arg: arg
[/python]
And that's it! Now we have simplest and simple2 which behave the exact same way, but the former we constructed with much less jargon; however, technically speaking we only saved two characters in this case, so what's the big deal?
If we look in detail at the lambda
statement we find that it is actually a statement that returns a function (which is why we assign it to a variable), and this is where the real power of the lambda
construct is, so let's look at an example where we harness this power.
Let's say we have a list of 3-tuples which looks like this:
[python]
tups = [
(1, 3, -2),
(3, 2, 1),
(-1, 0, 4),
(0, -1, 3),
(-2, 6, -5)
]
[/python]
If we want a sorted version of tups we'd simply have to give it to the built-in sorted
method:
[python]
>>> sorted(tups)
[(-2, 6, -5), (-1, 0, 4), (0, -1, 3), (1, 3, -2), (3, 2, 1)]
[/python]
This is fine if we only want to sort by the first value in each tuple, but what if we want to sort by the second or third value? Knowing how the built-in sorted
method works, we can use the key argument to define a function that will return the desired value (see How to Sort Python Dictionaries by Key or Value for some background on sorted
). Here's how it would look for sorting with the 2nd value in each tuple:
[python]
>>> def sortkey(tup):
... return tup[1]
>>> sorted(tups, key=sortkey)
[(0, -1, 3), (-1, 0, 4), (3, 2, 1), (1, 3, -2), (-2, 6, -5)]
[/python]
This works perfectly, but we've used up extra space/lines (if in a script file), and extra memory for a one-statement function that only helps to sort our list. If using a different language, we might have no choice but to do this (or worse), but fortunately we have the lambda
function construct :-). With it we can define the same function in a simpler form:
[python]
# Returns a function
>>> lambda tup: tup[1]
<function <lambda> at 0x02BD1230>
[/python]
In the case of simplest we assigned the lambda function returned by the lambda
construct/statement to a value, but the power of the lambda construct is we don't have to do that. Instead we can simply use the statement directly in sorted
for the key:
[python]
>>> sorted(tups, key=lambda tup: tup[1])
[(0, -1, 3), (-1, 0, 4), (3, 2, 1), (1, 3, -2), (-2, 6, -5)]
[/python]
It works the same way as with sortkey
, but by using this form the process is simpler and saves lines and memory!
This is the power of lambda
functions and their construct, but the best part is it will also work for any part of your script that needs such a function. That includes the built-in sorting/iterating functions (e.g. sorted
, map
, and filter
), class methods such as re.sub
(with the repl
argument as a function), instance methods (as with list.sort
), callback functions for Tkinter
widgets, etc. So don't hesitate to put lambda
functions to work and explore all that they are capable of doing!