Functions And Functional Basics
Lambda Functions & map/filter/reduce
A lambda is a small, anonymous (unnamed) function defined in a single expression — no def, no name, no return keyword (the expression's value is returned automa
Jr Codex Python Notes
Level: Intermediate Prerequisites: Chapter 5 Time to complete: ~20 minutes
Table of Contents
- What is a Lambda?
- Lambda vs a Named Function
- Where Lambdas Actually Get Used
map()filter()functools.reduce()- Comprehensions vs map/filter — Which to Prefer
- Summary & Next Steps
1. What is a Lambda?
A lambda is a small, anonymous (unnamed) function defined in a single expression — no def, no name, no return keyword (the expression's value is returned automatically).
square = lambda x: x ** 2
print(square(5)) # 25
add = lambda a, b: a + b
print(add(3, 4)) # 7Lambda Anatomy
─────────────────────────────────────────
lambda x : x ** 2
↑ ↑ ↑
keyword param expression (implicitly returned)
─────────────────────────────────────────
Equivalent def version, for comparison:
def square(x):
return x ** 2A lambda is limited to a single expression — no statements, no multiple lines, no if/for blocks (though a ternary expression is allowed since it's still one expression):
classify = lambda n: "even" if n % 2 == 0 else "odd"
print(classify(4)) # "even"2. Lambda vs a Named Function
lambda | def | |
|---|---|---|
| Has a name? | No (anonymous) — though you can assign it to a variable | Yes |
| Body | Single expression only | Any number of statements |
| Docstring support | No | Yes |
| Typical use | Short, throwaway, passed inline to another function | Anything reused, tested, or non-trivial |
Style guideline (PEP 8): don't assign a lambda to a name just to call it later — use def instead. Lambdas are meant to be used inline, right where they're needed.
# Discouraged — just use def instead
square = lambda x: x ** 2
# Preferred for anything with a name
def square(x):
return x ** 2
# This is where lambdas actually shine — passed directly as an argument
sorted([3, 1, 2], key=lambda x: -x) # inline, no name needed3. Where Lambdas Actually Get Used
The most common real-world use is as a key function for sorting:
students = [
{"name": "Alice", "grade": 85},
{"name": "Bob", "grade": 92},
{"name": "Charlie", "grade": 78},
]
# Sort by grade, descending
by_grade = sorted(students, key=lambda s: s["grade"], reverse=True)
for s in by_grade:
print(s["name"], s["grade"])
# Bob 92
# Alice 85
# Charlie 78
# Sort tuples by their second element
pairs = [(1, "b"), (3, "a"), (2, "c")]
pairs.sort(key=lambda pair: pair[1])
print(pairs) # [(3, 'a'), (1, 'b'), (2, 'c')]4. map()
Applies a function to every item in an iterable, returning a lazy map object (similar to a generator — see Chapter 5).
numbers = [1, 2, 3, 4, 5]
doubled = map(lambda x: x * 2, numbers)
print(list(doubled)) # [2, 4, 6, 8, 10] — must convert to list to see all values
# map() also works with a regular named function
def celsius_to_fahrenheit(c):
return c * 9/5 + 32
temps_c = [0, 20, 37, 100]
temps_f = list(map(celsius_to_fahrenheit, temps_c))
print(temps_f) # [32.0, 68.0, 98.6, 212.0]Equivalent list comprehension (usually the more Pythonic choice — see Section 7):
doubled = [x * 2 for x in numbers]5. filter()
Keeps only the items for which a function returns True.
numbers = range(1, 11)
evens = filter(lambda x: x % 2 == 0, numbers)
print(list(evens)) # [2, 4, 6, 8, 10]
words = ["apple", "hi", "banana", "ok", "cherry"]
long_words = filter(lambda w: len(w) > 3, words)
print(list(long_words)) # ['apple', 'banana', 'cherry']Equivalent list comprehension:
evens = [x for x in numbers if x % 2 == 0]6. functools.reduce()
Combines all items in an iterable into a single cumulative value, by repeatedly applying a function to a running total and the next item.
from functools import reduce
numbers = [1, 2, 3, 4, 5]
total = reduce(lambda acc, x: acc + x, numbers)
print(total) # 15
product = reduce(lambda acc, x: acc * x, numbers)
print(product) # 120
# With an explicit starting value
total_plus_100 = reduce(lambda acc, x: acc + x, numbers, 100)
print(total_plus_100) # 115reduce() Step by Step — sum of [1, 2, 3, 4, 5]
─────────────────────────────────────────
step 1: acc=1, x=2 → acc = 1 + 2 = 3
step 2: acc=3, x=3 → acc = 3 + 3 = 6
step 3: acc=6, x=4 → acc = 6 + 4 = 10
step 4: acc=10, x=5 → acc = 10 + 5 = 15
final result: 15
─────────────────────────────────────────
Unlike map/filter, reduce isn't a built-in — it lives in functools and needs an explicit import. Note also that for simple sums/products, Python's built-in sum() and math.prod() are clearer than reduce — save reduce for genuinely custom accumulation logic.
7. Comprehensions vs map/filter — Which to Prefer
numbers = [1, 2, 3, 4, 5]
# map + lambda
result1 = list(map(lambda x: x * 2, numbers))
# list comprehension — same result
result2 = [x * 2 for x in numbers]
# filter + lambda
result3 = list(filter(lambda x: x % 2 == 0, numbers))
# list comprehension — same result
result4 = [x for x in numbers if x % 2 == 0]Python community convention (PEP 8 spirit): prefer comprehensions over map()/filter() with a lambda — they're generally considered more readable and Pythonic. Reach for map/filter mainly when:
- You already have a named function (not a lambda) to pass in —
map(str.upper, words)reads cleanly. - You're chaining functional operations in a style borrowed from other languages, and the team already favors that idiom.
| Tool | Prefer When |
|---|---|
| List/dict/set comprehension | Default choice — most readable for transform/filter |
map() / filter() | You already have a named function handy, no lambda needed |
functools.reduce() | Genuine custom accumulation — otherwise use sum(), max(), etc. |
8. Summary & Next Steps
Key Takeaways
- A
lambdais a single-expression, unnamed function — ideal for short, inline use (like asortkey), not for anything you'd want to name and reuse. map(func, iterable)transforms every item;filter(func, iterable)keeps items wherefuncreturnsTrue. Both return lazy iterators — wrap inlist()to see all results.functools.reduce(func, iterable)collapses an iterable into a single accumulated value.- Comprehensions are generally preferred over
map/filter+lambdafor readability — reserve lambdas for cases like sort keys where naming a function would be overkill.
Module 2 Complete — Next Module
You now know how to package logic into functions, control their arguments and scope, and use Python's functional tools (comprehensions, lambda, map/filter/reduce). Module 3 shifts to organizing code across files and handling the real world — modules, file I/O, and errors.
Concept Check
- Why can't a lambda contain a
forloop or multiple statements? - Rewrite
list(filter(lambda x: x > 0, numbers))as a list comprehension. - What does
reduce(lambda acc, x: acc + x, [1,2,3], 100)return, and why does the100matter?
Next Chapter
→ Module 3: Modules, Data & Errors
Jr Codex — 1-on-1 Personalized Coaching | Back to Module Index