DEV Community

Cover image for Lambda, Map, and Filter: Functional Python Explained
Akhilesh
Akhilesh

Posted on

Lambda, Map, and Filter: Functional Python Explained

You know how to build lists with comprehensions now.

doubled = [n * 2 for n in numbers]
evens = [n for n in numbers if n % 2 == 0]
Enter fullscreen mode Exit fullscreen mode

Clean. Readable. Good.

Now you are going to see the older way Python does the same things. Not because it is better. Because you will absolutely see this code in tutorials, libraries, and other people's projects. If you do not know what lambda, map, and filter are, that code will confuse you.


Lambda: A Function With No Name

A regular function needs a name, a def, parameters, a body, a return.

def double(n):
    return n * 2
Enter fullscreen mode Exit fullscreen mode

A lambda is a function stripped to its bare minimum. No def. No name. No return keyword. Just the parameters and the expression.

double = lambda n: n * 2
Enter fullscreen mode Exit fullscreen mode

Same thing. One line.

Call it exactly like a regular function.

print(double(5))
print(double(10))
Enter fullscreen mode Exit fullscreen mode

Output:

10
20
Enter fullscreen mode Exit fullscreen mode

The syntax is lambda parameters: expression. Whatever the expression evaluates to gets returned automatically.

Multiple parameters work too.

add = lambda a, b: a + b
print(add(3, 4))
Enter fullscreen mode Exit fullscreen mode

Output:

7
Enter fullscreen mode Exit fullscreen mode

When Lambda Makes Sense

Storing a lambda in a variable like double = lambda n: n * 2 is actually considered bad practice. If you are naming it, just use def. It is clearer.

Lambda earns its place when you need a small function right now, inline, without giving it a name. The most common case is passing a function as an argument to another function.

names = ["Priya", "Alex", "Jordan", "Sam"]
names.sort(key=lambda name: len(name))
print(names)
Enter fullscreen mode Exit fullscreen mode

Output:

['Sam', 'Alex', 'Priya', 'Jordan']
Enter fullscreen mode Exit fullscreen mode

sort accepts a key argument. It calls that function on each item and sorts by the result. The lambda lambda name: len(name) says: use the length of each name as the sort key.

You could write a named function for this. But why? The lambda is short, it is only used once, and it sits right where it is needed. This is exactly what lambdas are for.


Map: Transform Every Item

map applies a function to every item in an iterable and gives you back the transformed items.

numbers = [1, 2, 3, 4, 5]
doubled = list(map(lambda n: n * 2, numbers))
print(doubled)
Enter fullscreen mode Exit fullscreen mode

Output:

[2, 4, 6, 8, 10]
Enter fullscreen mode Exit fullscreen mode

map(function, iterable) takes a function and an iterable. It calls the function on each item. You wrap it in list() because map returns a lazy object, not a list directly. More on lazy evaluation another time.

Compare to the comprehension version:

doubled = [n * 2 for n in numbers]
Enter fullscreen mode Exit fullscreen mode

Same result. Most Python developers today prefer the comprehension. It reads more naturally. But map shows up in older code and in some specific situations where it is genuinely cleaner.

names = ["alex", "priya", "sam"]
capitalized = list(map(str.capitalize, names))
print(capitalized)
Enter fullscreen mode Exit fullscreen mode

Output:

['Alex', 'Priya', 'Sam']
Enter fullscreen mode Exit fullscreen mode

Notice str.capitalize with no parentheses and no lambda. When the transformation is already a method, you can pass it directly without wrapping it. Clean.


Filter: Keep Only What Passes

filter keeps items where the function returns True and drops the rest.

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = list(filter(lambda n: n % 2 == 0, numbers))
print(evens)
Enter fullscreen mode Exit fullscreen mode

Output:

[2, 4, 6, 8, 10]
Enter fullscreen mode Exit fullscreen mode

filter(function, iterable) calls the function on each item. Items where the function returns True make it through. Items where it returns False get dropped.

Comprehension equivalent:

evens = [n for n in numbers if n % 2 == 0]
Enter fullscreen mode Exit fullscreen mode

Again, same result, different syntax. The comprehension is preferred in modern Python. But filter is there, it works, and you will see it.


Using a Real Function Instead of Lambda

Lambda is not required. Any function works.

def is_passing(score):
    return score >= 60

scores = [45, 92, 78, 34, 61, 88, 55]
passing = list(filter(is_passing, scores))
print(passing)
Enter fullscreen mode Exit fullscreen mode

Output:

[92, 78, 61, 88]
Enter fullscreen mode Exit fullscreen mode

When the condition is more than a one-liner, write a proper function and pass it in. Lambda is only convenient when the logic is simple enough to fit on one line.


Combining Map and Filter

You can chain them. Filter first to keep only the relevant items, then map to transform them.

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

result = list(map(lambda n: n ** 2, filter(lambda n: n % 2 == 0, numbers)))
print(result)
Enter fullscreen mode Exit fullscreen mode

Output:

[4, 16, 36, 64, 100]
Enter fullscreen mode Exit fullscreen mode

Filter keeps the even numbers. Map squares them. But honestly, look at that line. It is getting hard to read.

The comprehension version is cleaner:

result = [n ** 2 for n in numbers if n % 2 == 0]
Enter fullscreen mode Exit fullscreen mode

Same output. One read. This is why most Python developers reach for comprehensions over map and filter by default.


Sorted With a Key

One place where lambda genuinely shines is sorted with a custom key.

students = [
    {"name": "Alex", "score": 92},
    {"name": "Priya", "score": 78},
    {"name": "Sam", "score": 85},
    {"name": "Jordan", "score": 61}
]

by_score = sorted(students, key=lambda s: s["score"], reverse=True)

for student in by_score:
    print(f"{student['name']}: {student['score']}")
Enter fullscreen mode Exit fullscreen mode

Output:

Alex: 92
Sam: 85
Priya: 78
Jordan: 61
Enter fullscreen mode Exit fullscreen mode

Sorting a list of dictionaries by one of the dictionary keys. The lambda grabs the score from each student dictionary. reverse=True puts highest first. This pattern comes up constantly in data work.


The Honest Summary

Lambda, map, and filter come from a style of programming called functional programming. Python supports this style but was not built around it the way some languages are.

In practice:

Use list comprehensions for most transformations and filters. They are more readable and more Pythonic.

Use lambda when you need a small throwaway function as an argument, especially for sorted, sort, max, and min with a custom key.

Use map and filter when you encounter them in existing code or when working with streams of data where the lazy evaluation matters.

Know all three because you will see all three.


Try This

Create functional_practice.py.

Start with this data:

products = [
    {"name": "Laptop", "price": 75000, "category": "Electronics"},
    {"name": "Shirt", "price": 800, "category": "Clothing"},
    {"name": "Headphones", "price": 3500, "category": "Electronics"},
    {"name": "Jeans", "price": 1500, "category": "Clothing"},
    {"name": "Phone", "price": 45000, "category": "Electronics"},
    {"name": "Jacket", "price": 4000, "category": "Clothing"}
]
Enter fullscreen mode Exit fullscreen mode

Do all of this, once with lambda and map or filter, then again with a comprehension, and print both results to confirm they match:

Get a list of just the product names.

Get a list of products that cost more than 3000.

Get a list of all prices with a 10 percent discount applied.

Sort the entire products list by price from lowest to highest using sorted and a lambda key.


What's Next

One more post in Phase 1. Decorators. They look strange the first time you see them but the concept behind them is simple and they show up constantly in web frameworks, logging, authentication, and ML code. After that, Phase 1 is done and we move into the math that makes AI work.

Top comments (0)