Lambdas Are Single-Expression Functions
- The lambda keyword in Python provides a shortcut for declaring small anonymous functions.
- Lambda functions behave just like regular functions declared with the def keyword.
- They can be used whenever function objects are required.
For example, this is how youâd define a simple lambda function carrying
out an addition:
>>> add = lambda x, y: x + y
>>> add(5, 3)
8
You could declare the same add function with the def keyword, but it would be slightly more verbose:
>>> def add(x, y):
... return x + y
>>> add(5, 3)
8
Now you might be wondering, Why the big fuss about lambdas?
If theyâre just a slightly more concise version of declaring functions with def, whatâs the big deal?
Take a look at the following example and keep the words function expression in your head while you do that:
>>> (lambda x, y: x + y)(5, 3)
8
Okay, what happened here?
I just used lambda to define an âaddâ function inline and then immediately called it with the arguments 5 and 3.
Conceptually, the lambda expression lambda x, y: x + y is the
same as declaring a function with def, but just written inline.
The key difference here is that I didnât have to bind the function object to a name before I used it.
I simply stated the expression I wanted to compute as part of a lambda, and then immediately evaluated it by calling the lambda expression like a regular function.
Thereâs another syntactic difference between lambdas and regular
function definitions.
Lambda functions are restricted to a single expression.
This means a lambda function canât use statements or annotationsânot even a return statement.
How do you return values from lambdas then?
Executing a lambda function evaluates its expression and then automatically returns the expressionâs result, so thereâs always an implicit return statement.
Thatâs why some people refer to lambdas as single expression
functions.
Lambdas You Can Use
- When should you use lambda functions in your code?
- Technically, any time youâre expected to supply a function object you can use a lambda expression.
- And because lambdas can be anonymous, you donât even need to assign them to a name first.
This can provide a handy and âunbureaucraticâ shortcut to defining a function in Python.
My most frequent use case for lambdas is writing short and concise key funcs for sorting iterables by an alternate key:
>>> tuples = [(1, 'd'), (2, 'b'), (4, 'a'), (3, 'c')]
>>> sorted(tuples, key=lambda x: x[1])
[(4, 'a'), (2, 'b'), (3, 'c'), (1, 'd')]
In the above example, weâre sorting a list of tuples by the second value in each tuple.
In this case, the lambda function provides a quick way to modify the sort order.
Hereâs another sorting example you can play with:
>>> sorted(range(-5, 6), key=lambda x: x * x)
[0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5]
Both examples I showed you have more concise implementations in
Python using the built-in operator.itemgetter() and abs() functions.
But I hope you can see how using a lambda gives you much
more flexibility.
Want to sort a sequence by some arbitrary computed key?
No problem. Now you know how to do it.
Hereâs another interesting thing about lambdas:
Just like regular nested functions, lambdas also work as lexical closures.
Whatâs a lexical closure?
Itâs just a fancy name for a function that remembers the values from the enclosing lexical scope even when the program flow is no longer in that scope.
Hereâs a (fairly academic) example to illustrate the idea:
>>> def make_adder(n):
... return lambda x: x + n
>>> plus_3 = make_adder(3)
>>> plus_5 = make_adder(5)
>>> plus_3(4)
7
>>> plus_5(4)
9
In the above example
The x + n lambda can still access the value of n even though it was defined in the make_adder function (the enclosing scope).
Sometimes, using a lambda function instead of a nested function
declared with the def keyword can express the programmerâs intent
more clearly.
But to be honest, this isnât a common occurrenceâat least not in the kind of code that I like to write. So letâs talk a little more about that.
But Maybe You ShouldnâtâŚ
- On the one hand, Iâm hoping this chapter got you interested in exploring Pythonâs lambda functions.
- On the other hand, I feel like itâs time to put up another caveat
- Lambda functions should be used sparingly and with extraordinary care.
I know Iâve written my fair share of code using lambdas that looked âcoolâ but were actually a liability for me and my coworkers.
If youâre tempted to use a lambda, spend a few seconds (or minutes) to think if it is really the cleanest and most maintainable way to achieve the desired result.
For example, doing something like this to save two lines of code is just silly.
Sure, technically it works and itâs a nice enough âtrick.â
But itâs also going to confuse the next gal or guy that has to ship a bugfix under a tight deadline:
# Harmful:
>>> class Car:
... rev = lambda self: print('Wroom!')
... crash = lambda self: print('Boom!')
>>> my_car = Car()
>>> my_car.crash()
'Boom!'
I have similar feelings about complicated map() or filter() constructs using lambdas.
Usually itâs much cleaner to go with a list comprehension or generator expression:
# Harmful:
>>> list(filter(lambda x: x % 2 == 0, range(16)))
[0, 2, 4, 6, 8, 10, 12, 14]
# Better:
>>> [x for x in range(16) if x % 2 == 0]
[0, 2, 4, 6, 8, 10, 12, 14]
If you find yourself doing anything remotely complex with lambda
expressions, consider defining a standalone function with a proper
name instead.
Saving a few keystrokes wonât matter in the long run, but your colleagues (and your future self) will appreciate clean and readable code more than terse wizardry.
Key Takeaways
- Lambda functions are single-expression functions that are not necessarily bound to a name (anonymous).
- Lambda functions canât use regular Python statements and always include an implicit return statement.
- Always ask yourself: Would using a regular (named) function or a list comprehension offer more clarity?
Top comments (1)
Great article. I'd just stress that functions are statements, lambdas are expressions. Expressions can better fit some nooks - as shown.
If you assign a lambda expression to a variable then you would most likely be better using a function definition instead - also as shown :-)