Python Tutorial
Lambda Functions in Python
A lambda is a small anonymous function written in a single expression: lambda x: x * 2. Lambdas are most useful as short "key" or callback functions passed to other functions — sorting by a field, filtering, mapping — where defining a full named function would be overkill.
This lesson covers lambda syntax, using lambdas with sorted, min/max, map and filter, lambdas in dictionaries as simple dispatch tables, the late-binding pitfall, and when to prefer a regular def.
Syntax
lambda parameters: expression creates a function object that returns the expression's value. It can take any number of parameters (including defaults and *args) but must be a single expression — no statements, no assignments (except the walrus operator), no multiple lines. square = lambda x: x ** 2 works but PEP 8 recommends def when you give the function a name.
Where Lambdas Shine
As arguments to higher-order functions: sorted(people, key=lambda p: p["age"]), max(products, key=lambda p: p.price), filter(lambda n: n % 2, numbers), event handlers in GUI code (command=lambda: save(file)), and small dispatch dictionaries mapping names to operations.
Late Binding in Loops
A lambda created in a loop looks up loop variables when it is called, not when it is created, so all of them see the final value. Capture the current value with a default argument: lambda i=i: i.
Examples
Basic lambdas
add = lambda a, b: a + b
greet = lambda name="friend": f"Hello, {name}!"
is_even = lambda n: n % 2 == 0
print(add(3, 4), greet(), greet("Asha"), is_even(10))
print((lambda x: x ** 3)(4))
7 Hello, friend! Hello, Asha! True
64
Sorting and choosing with key functions
products = [
{"name": "Laptop", "price": 55000, "rating": 4.5},
{"name": "Mouse", "price": 700, "rating": 4.8},
{"name": "Keyboard", "price": 1500, "rating": 4.1},
]
by_price = sorted(products, key=lambda p: p["price"])
print([p["name"] for p in by_price])
print(max(products, key=lambda p: p["rating"])["name"])
print(sorted(["banana", "Apple", "cherry"], key=lambda s: s.lower()))
print(sorted([(1, "b"), (1, "a"), (0, "z")], key=lambda t: (t[0], t[1])))
['Mouse', 'Keyboard', 'Laptop']
Mouse
['Apple', 'banana', 'cherry']
[(0, 'z'), (1, 'a'), (1, 'b')]
map, filter and a dispatch table
numbers = [1, 2, 3, 4, 5, 6]
print(list(map(lambda n: n * n, numbers)))
print(list(filter(lambda n: n % 2 == 0, numbers)))
operations = {
"+": lambda a, b: a + b,
"-": lambda a, b: a - b,
"*": lambda a, b: a * b,
"/": lambda a, b: a / b if b else "cannot divide by zero",
}
for op in "+-*/":
print(f"8 {op} 2 =", operations[op](8, 2))
print(operations["/"](1, 0))
[1, 4, 9, 16, 25, 36]
[2, 4, 6]
8 + 2 = 10
8 - 2 = 6
8 * 2 = 16
8 / 2 = 4.0
cannot divide by zero
The late-binding pitfall and its fix
buggy = [lambda: i for i in range(3)]
fixed = [lambda i=i: i for i in range(3)]
print([f() for f in buggy])
print([f() for f in fixed])
[2, 2, 2]
[0, 1, 2]
Common Mistakes
- Assigning lambdas to names instead of using def (PEP 8 recommends def).
- Cramming complex logic into a lambda instead of writing a readable function.
- Late binding in loops: capture loop variables with a default argument.
- Using map/filter with lambdas where a comprehension is clearer.
Key Points to Remember
- lambda args: expression creates a small anonymous function.
- Lambdas are ideal as key functions and short callbacks.
- They are limited to one expression.
- Capture loop variables with default arguments to avoid late binding.
- Prefer def for anything named, reused or non-trivial.
Practice the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.