Lambdas
Contents
Lambdas#
Recall earlier when we were learning pandas
, we learned that the apply
function could take a function as another parameter! Instead of talking about pandas
, we will simplify this to write our own apply_fun
function that does something similar to a list of values. It takes a list of values and another function as a parameter, and returns a new list that is the result of applying the given function to each element in the input list.
def apply_fun(values, function):
# Use a list comprehension to apply function to each value
return [function(v) for v in values]
def times_two(x):
return 2 * x
numbers = [i for i in range(10)]
print('numbers :', numbers)
print('times two:', apply_fun(numbers, times_two))
Notice that in this example, we treat the function
parameter just like any other parameter, but we are now using it as a function to call (because we are saying the client passes in a function).
It’s a bit tedious that we have to write out a whole function called times_two
just so we can pass it in as a parameter. Multiplying something by two should be simple enough so it would be nice if there were a way to use a short-hand to do this for simple operations.
Enter the lambda (commonly called an anonymous function). The idea behind a lambda is to let you specify a function without needing to go through the whole def
syntax. This works best for very simple operations. Below is an example showing how to do this with our apply_fun
.
def apply_fun(values, function):
# Use a list comprehension to apply function to each value
return [function(v) for v in values]
numbers = [i for i in range(10)]
print('numbers :', numbers)
print('times two:', apply_fun(numbers, lambda v: 2 * v))
Notice instead of passing a function named times_two
as the second parameter, we pass lambda v: 2 * v
. The lambda
keyword defines a new function without giving it a name (hence, anonymous function ). The way to read this is it is a function that takes a single parameter v
and it returns the value of 2 * v
. This is essentially just short-hand for the previous example, with the benefit that we don’t have to define a whole function called times_two
to do this.
By design, it is very difficult to do something more complex than a one-line expression inside a lambda
since it is meant to be a super quick-and-easy way of defining functions for simple operations.
An Application: Sorting#
One of the most common places lambdas
show up is for sorting values. Suppose we wanted to use our Dog
class to make a list
of Dog
s. Additionally, suppose I wanted to sort them by their name (alphabetically). There is a function in Python call sorted
that sorts a list of values and returns a new list that has all the values of the input in sorted order.
class Dog:
def __init__(self, name):
self._name = name
def get_name(self):
return self._name
dogs = [Dog('Bella'), Dog('Scout'), Dog('Chester')]
dogs = sorted(dogs)
# Should print in sorted order!
for dog in dogs:
print(dog.get_name())
This runs into a bug though, because Python doesn’t know how we want to sort the Dog
objects! There are ways to define how to compare Dog
s, which we will see briefly in the next lesson.
However, a common workaround is to use an optional parameter for the sorted
function named key
. The value of key
should be a function that takes a single element of the list and returns a value that Python knows how to sort (like a number or a str
); this way Python will sort the Dog
s based on the value that results from their key
function.
So to do this in our example, we need to pass a function as the key
to transform each Dog
into its name so that we can sort it by their name. This is very easy to do with a lambda
!
class Dog:
def __init__(self, name):
self._name = name
def get_name(self):
return self._name
dogs = [Dog('Bella'), Dog('Scout'), Dog('Chester')]
dogs = sorted(dogs, key=lambda d: d.get_name())
# Should print in sorted order!
for dog in dogs:
print(dog.get_name())
The way this works is in the sorting algorithm, instead of comparing the Dog
s themselves, the algorithm compares the results of applying key
to each Dog
so it is sorted by key
. The power of this comes from if your class had multiple things that you might want to sort by. You could now tell the sorted
function how you want them to be sorted by passing in different key
functions each time!