1. Introduction
A lambda function is a small, anonymous (unnamed) function defined with the lambda keyword instead of def. Lambdas are restricted to a single expression, which is automatically returned, making them convenient for short, throwaway pieces of logic that are used once, often as arguments to higher-order functions like map(), filter(), and sorted().
Cricket analogy: A substitute fielder called on for just one over with a single job -- field at deep midwicket -- and then leaves, is like a lambda: a quick, unnamed, one-task function passed straight into sorted() or map().
Lambdas do not support multiple statements, annotations, or default docstrings the way regular functions do, so they are best reserved for simple expressions rather than complex logic.
Cricket analogy: A pinch hitter sent in for one over can only swing the bat, not also captain the side or review DRS decisions -- lambdas similarly can't hold multiple statements, annotations, or docstrings like a full function.
2. Syntax
square = lambda x: x ** 2
add = lambda a, b: a + b
sorted(some_list, key=lambda item: item.value)
3. Explanation
A lambda expression takes the form lambda parameters: expression. It can take any number of arguments (including default values and *args/**kwargs) but must consist of a single expression whose result is implicitly returned. Lambdas are commonly passed as the key argument to sorted(), max(), min(), or used inside map() and filter().
Cricket analogy: 'lambda player: player.runs' used as the key in sorted() is like a scorer sorting the whole batting lineup by runs scored -- one quick rule applied to every player, taking any number of stats as input.
Late-binding closure trap: a lambda created inside a loop does not capture the loop variable's value at creation time — it captures the VARIABLE itself, which is looked up when the lambda is finally called. If several lambdas are created across loop iterations and called after the loop finishes, they all see the loop variable's FINAL value, not the value at the time each lambda was created. The fix is to bind the current value as a default argument, e.g. lambda i=i: i.
4. Example
squares = list(map(lambda x: x ** 2, range(1, 6)))
print(squares)
names = ["banana", "kiwi", "apple", "fig"]
names.sort(key=lambda s: len(s))
print(names)
funcs = []
for i in range(3):
funcs.append(lambda: i)
print([f() for f in funcs])
funcs_fixed = []
for i in range(3):
funcs_fixed.append(lambda i=i: i)
print([f() for f in funcs_fixed])
5. Output
[1, 4, 9, 16, 25]
['fig', 'kiwi', 'apple', 'banana']
[2, 2, 2]
[0, 1, 2]
6. Key Takeaways
- lambda parameters: expression creates a small anonymous function limited to a single expression.
- Lambdas are commonly used as the key argument for sorted(), max(), min(), and inside map()/filter().
- Lambdas created in a loop capture the loop variable by reference, not by value, due to late binding.
- The fix for late binding is to add a default argument, e.g. lambda i=i: i, which captures the value at definition time.
- For anything beyond a single simple expression, a regular def function is clearer and preferred.
Practice what you learned
1. What is the maximum number of expressions a lambda function body can contain?
2. In the Example, why does print([f() for f in funcs]) output [2, 2, 2] instead of [0, 1, 2]?
3. How does lambda i=i: i fix the late-binding closure problem?
4. Which higher-order function commonly takes a lambda as its 'key' argument to control sort order?
5. What does list(map(lambda x: x ** 2, range(1, 6))) evaluate to?
6. Why might a developer prefer a regular def function over a lambda?
Was this page helpful?
You May Also Like
Functions in Python
How to define, call, and document reusable blocks of code with Python functions, including the def keyword and implicit None return.
List Comprehension in Python
A concise Python syntax for building lists from iterables in a single expression, including conditionals and the memory-difference vs generator expressions.
Scope and Namespaces in Python
Understanding Python's LEGB scope resolution order and how the global and nonlocal keywords let functions modify variables outside their local scope.
Decorators in Python
Learn how Python decorators use the @syntax to wrap functions, adding behavior like logging or timing without changing the original function's code.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics