A lambda is a small anonymous function defined in a single expression. It is not a replacement for def — it is a tool for situations where you need a short, throwaway function and giving it a name would add more noise than clarity.
The syntax
lambda arguments: expression
A lambda can take any number of arguments but contains only a single expression. The result of that expression is automatically returned.
square = lambda x: x ** 2
print(square(5)) # 25
add = lambda x, y: x + y
print(add(3, 4)) # 7
Both of these are equivalent to named functions. The lambda form is only worth using when you are passing the function inline somewhere else.
Sorting with a key function
The most common real-world use for lambdas is as the key argument to sorted() or list.sort().
students = [
{'name': 'Alice', 'grade': 88},
{'name': 'Bob', 'grade': 95},
{'name': 'Charlie', 'grade': 72},
]
# Sort by grade descending
sorted_students = sorted(students, key=lambda s: s['grade'], reverse=True)
# [{'name': 'Bob', 'grade': 95}, {'name': 'Alice', 'grade': 88}, ...]
Sorting by multiple fields:
data = [('Alice', 2), ('Bob', 1), ('Alice', 1)]
sorted_data = sorted(data, key=lambda x: (x[0], x[1]))
# [('Alice', 1), ('Alice', 2), ('Bob', 1)]
With filter()
A lambda pairs naturally with filter() to keep only elements that satisfy a condition:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = list(filter(lambda x: x % 2 == 0, numbers))
# [2, 4, 6, 8, 10]
With map()
To apply a transformation to every element in a sequence:
prices = [10.5, 20.0, 5.75, 8.99]
discounted = list(map(lambda p: round(p * 0.9, 2), prices))
# [9.45, 18.0, 5.17, 8.09]
Conditional logic inside a lambda
You can use a ternary expression inside a lambda for simple branching:
classify = lambda x: 'positive' if x > 0 else ('negative' if x < 0 else 'zero')
print(classify(5)) # positive
print(classify(-3)) # negative
print(classify(0)) # zero
When not to use a lambda
Lambdas are meant for short, readable one-liners. If the logic requires more than a single expression, use a named function instead. PEP 8 specifically advises against assigning a lambda to a variable at module level — that is exactly what def is for. The goal is clarity. A lambda that requires a comment to explain is a lambda that should be a function.
# Avoid this — too complex for a lambda
process = lambda x: x['value'] * 1.1 if x['type'] == 'A' else x['value'] * 0.95 if x['type'] == 'B' else x['value']
# Prefer this
def apply_discount(x):
if x['type'] == 'A':
return x['value'] * 1.1
elif x['type'] == 'B':
return x['value'] * 0.95
return x['value']
Use lambdas to reduce clutter, not to create it.