A lambda is a small anonymous function written in a single expression: lambda x: x * 2. It is most useful when you need a throwaway function to hand to another function. map() applies a function to every item, filter() keeps only the items for which a function returns true, and reduce() (from functools) combines all the items into a single value.
This guide explains each with real output, shows when a comprehension is the better choice, and covers the traps.
In this guide
The short version
lambda args: expression– a tiny function with no name and one expression.map(f, items)– applyfto each item.filter(f, items)– keep items wheref(item)is true.reduce(f, items)– combine items pairwise into one value (import it fromfunctools).mapandfilterreturn lazy iterators: wrap them inlist()to see the results.
What is a lambda?
A lambda is a function without a def and without a name. The part before the colon is the parameters, and the part after is the single expression whose value is returned automatically:
square = lambda x: x * x
add = lambda a, b: a + b
print(square(4), add(2, 3))
print((lambda x: x + 1)(5))
Output
16 5
6
lambda x: x * x does the same as def square(x): return x * x. You can even call one immediately, as in the last line. A lambda can hold only one expression: no statements, no assignments and no multiple lines. For anything longer, use a normal def (see Python Functions).
One small giveaway that a lambda has no real name:
f = lambda x: x * 2
def g(x):
return x * 2
print(f.__name__, g.__name__)
Output
<lambda> g
That is why assigning a lambda to a variable (f = lambda ...) is discouraged. If it needs a name, write a def.
Where lambdas earn their keep: sorting and max/min
The most common real use is the key argument of sorted(), max() and min(). The key function says what to compare:
students = [("Asha", 90), ("Ravi", 72), ("Meera", 85)]
print(sorted(students, key=lambda s: s[1]))
print(sorted(students, key=lambda s: s[1], reverse=True)[0])
print(max(students, key=lambda s: s[1]))
words = ["banana", "kiwi", "apple", "fig"]
print(sorted(words, key=lambda w: len(w)))
Output
[('Ravi', 72), ('Meera', 85), ('Asha', 90)]
('Asha', 90)
('Asha', 90)
['fig', 'kiwi', 'apple', 'banana']
Each lambda picks the part of the item to sort by: the score, or the length of the word. For simple lookups, operator.itemgetter does the same and is a little faster and clearer:
from operator import itemgetter
students = [("Asha", 90), ("Ravi", 72), ("Meera", 85)]
print(sorted(students, key=itemgetter(1)))
Output
[('Ravi', 72), ('Meera', 85), ('Asha', 90)]
map(): transform every item
map(function, iterable) calls the function on each item and gives you the results. With two iterables, it passes one item from each:
nums = [1, 2, 3, 4]
print(list(map(lambda x: x * 10, nums)))
print(list(map(str, nums)))
print(list(map(lambda a, b: a + b, [1, 2, 3], [10, 20, 30])))
m = map(str, nums)
print(type(m).__name__)
Output
[10, 20, 30, 40]
['1', '2', '3', '4']
[11, 22, 33]
map
Notice the last line: map returns a map object, a lazy iterator, not a list. Nothing is computed until you loop over it or wrap it in list(). (For how lazy iterators work, see Python Iterators and Generators Explained.)
filter(): keep some items
filter(function, iterable) keeps the items where the function returns a true value. Pass None as the function to keep every truthy item, which is a handy way to drop empty values:
nums = [1, 2, 3, 4, 5, 6]
print(list(filter(lambda x: x % 2 == 0, nums)))
print(list(filter(None, [0, 1, "", "a", None, [], [0]])))
print(list(filter(str.isdigit, ["12", "ab", "7", ""])))
Output
[2, 4, 6]
[1, 'a', [0]]
['12', '7']
The second line dropped 0, the empty string, None and the empty list, but kept [0] because a non-empty list is truthy. The third line passed an existing method, str.isdigit, instead of a lambda, which is always neater when a suitable function already exists.
reduce(): boil a list down to one value
reduce(function, items) takes the first two items, combines them with the function, then combines that result with the third, and so on. It lives in functools because in Python 3 it is not a built-in:
from functools import reduce
nums = [1, 2, 3, 4]
print(reduce(lambda a, b: a + b, nums))
print(reduce(lambda a, b: a * b, nums))
print(reduce(lambda a, b: a + b, nums, 100))
print(reduce(max, [3, 9, 2]))
Output
10
24
110
9
Here is what reduce(lambda a, b: a + b, [1, 2, 3, 4]) does, step by step:
| Step | a (running result) | b (next item) | a + b |
|---|---|---|---|
| 1 | 1 | 2 | 3 |
| 2 | 3 | 3 | 6 |
| 3 | 6 | 4 | 10 |
The third line above passed a starting value, 100, which becomes the first a. For plain adding, though, use sum(), and for the biggest value use max(). Python already has built-ins for the common reductions, so reduce is for the unusual ones.
The three tools chain together. This adds up the squares of the even numbers:
from functools import reduce
nums = [1, 2, 3, 4, 5, 6]
evens = filter(lambda x: x % 2 == 0, nums)
squares = map(lambda x: x * x, evens)
print(reduce(lambda a, b: a + b, squares))
Output
56
map and filter vs comprehensions
Most Python programmers prefer a list comprehension for what map and filter do, because it reads more naturally and needs no lambda. They give identical results:
nums = [1, 2, 3, 4, 5, 6]
print(list(map(lambda x: x * x, nums)) == [x * x for x in nums])
print(list(filter(lambda x: x % 2 == 0, nums)) == [x for x in nums if x % 2 == 0])
print(sum(nums), sum(x * x for x in nums if x % 2 == 0))
Output
True
True
21 56
| Task | map / filter | Comprehension |
|---|---|---|
| Transform each item | list(map(lambda x: x * x, nums)) | [x * x for x in nums] |
| Keep some items | list(filter(lambda x: x % 2 == 0, nums)) | [x for x in nums if x % 2 == 0] |
| Both | map(f, filter(g, nums)) | [f(x) for x in nums if g(x)] |
A good rule: use a comprehension when you would need a lambda, and use map or filter when you already have a function to pass (map(str, nums), filter(str.isdigit, words)). More on comprehensions in Python List Comprehension Explained Simply.
Common mistakes
Mistake 1: forgetting that map and filter are lazy
They return iterators, and an iterator can be used only once. The second pass finds nothing:
nums = [1, 2, 3]
m = map(lambda x: x * 2, nums)
print(list(m))
print(list(m))
Output
[2, 4, 6]
[]
Wrap the result in list() if you need to reuse it.
Mistake 2: lambdas in a loop all see the last value
A lambda looks up its variables when it is called, not when it is created. Three lambdas made in a loop all share the same i, which ends at 2:
funcs = [lambda: i for i in range(3)]
print([f() for f in funcs])
funcs2 = [lambda i=i: i for i in range(3)]
print([f() for f in funcs2])
Output
[2, 2, 2]
[0, 1, 2]
The fix is to freeze the value with a default argument: lambda i=i: i.
Mistake 3: cramming logic into a lambda
If a lambda needs a conditional, a nested call or a comment to be understood, turn it into a named function. Readability matters more than saving two lines.
Mistake 4: using reduce when a built-in exists
sum(nums) beats reduce(lambda a, b: a + b, nums) every time.
Try it yourself
Work out each answer first, then open the solution.
1. Sort ["apple", "fig", "kiwi"] by the last letter of each word.
Show solution
print(sorted(["apple", "fig", "kiwi"], key=lambda w: w[-1]))
Output
['apple', 'fig', 'kiwi']The last letters are e, g and i, so the order is apple, fig, kiwi.
2. From ["asha", "Ravi", "Amit"] keep the names that start with A, whatever the case.
Show solution
names = ["asha", "Ravi", "Amit"]
print(list(filter(lambda n: n.lower().startswith("a"), names)))
Output
['asha', 'Amit']3. Use reduce to compute 5 factorial.
Show solution
from functools import reduce
print(reduce(lambda a, b: a * b, range(1, 6)))
Output
120It multiplies 1 × 2 × 3 × 4 × 5.
4. What does list(map(len, ["a", "bb", "ccc"])) return?
Show answer
print(list(map(len, ["a", "bb", "ccc"])))
Output
[1, 2, 3]You can pass any function to map, not only a lambda. len is called on each string.
Run these in our free Python compiler.
Frequently asked questions
What is a lambda function in Python?
A lambda is a small anonymous function defined in a single expression with the lambda keyword, for example lambda x: x * 2. It is mainly used for short throwaway functions such as sort keys.
What is the difference between lambda and def?
def creates a named function that can hold many statements. lambda creates an unnamed function limited to one expression. They produce the same kind of function object.
Why does map() return an object instead of a list?
In Python 3 map and filter are lazy: they compute items only when needed, which saves memory. Wrap them in list() to get all the results at once.
Where did reduce go in Python 3?
It moved out of the built-ins into the functools module. Import it with from functools import reduce.
Are map and filter faster than list comprehensions?
Not reliably. The difference is small either way. Choose based on readability, and measure only if speed is a real problem.
When should I avoid lambda?
When the logic is more than a simple expression, when you would assign it to a name, or when a built-in or operator function already does the job.
Related reading
- Python List Comprehension Explained Simply – the usual alternative to map and filter.
- Python Functions: Arguments, Return and Scope – functions as values.
- Python Decorators Explained Step by Step – more on passing functions around.
- Python Iterators and Generators Explained – why map returns an iterator.
Run this code in your browser
The free Upskly compiler runs Python with nothing to install. Paste the example, change it and see what happens.
Stuck on a traceback?
AI Assist works inside the Python notebook, so you can ask about an error or a concept without leaving the cell.
Test yourself
Timed questions on Decorators and Functional Tools, with an explanation for every answer.