Lambda functions are anonymous, single-expression functions defined inline. They are most useful when you need a simple function to pass as an argument โ to sorted(), map(), filter(), or a FastAPI response hook โ without the ceremony of a full def statement. Higher-order functions take other functions as arguments or return functions, enabling powerful data transformation patterns. Python’s built-in map(), filter(), and sorted() all accept functions as arguments and are commonly used in FastAPI for shaping query results and validating data collections.
Lambda Functions
# Syntax: lambda parameters: expression
# A lambda is a function โ it just has no name and no return statement
# Named function
def square(n):
return n ** 2
# Equivalent lambda
square_lambda = lambda n: n ** 2
print(square(5)) # 25
print(square_lambda(5)) # 25
# Multiple parameters
add = lambda a, b: a + b
print(add(3, 4)) # 7
# Lambda with default
greet = lambda name="World": f"Hello, {name}!"
print(greet()) # Hello, World!
print(greet("Alice")) # Hello, Alice!
# Immediately invoked (rare but valid)
result = (lambda x, y: x * y)(3, 4)
print(result) # 12
lambda x: "even" if x % 2 == 0 else "odd". If you need anything more complex โ local variables, multiple statements, or exception handling โ use a named def function. PEP 8 (Python’s style guide) actually discourages assigning a lambda to a variable; use def for that case.key argument to sorted(), min(), and max(). For example: sorted(posts, key=lambda p: p["created_at"], reverse=True) sorts posts by creation date in descending order without defining a separate function. This pattern is extremely common when shaping FastAPI query results.def instead. Code reviewers will flag complex lambdas as unreadable. Remember: code is read far more often than it is written โ optimise for the reader, not the writer.sorted() with Key Functions
posts = [
{"id": 3, "title": "C Post", "views": 150, "created": "2025-03-01"},
{"id": 1, "title": "A Post", "views": 500, "created": "2025-01-01"},
{"id": 2, "title": "B Post", "views": 75, "created": "2025-02-01"},
]
# Sort by a specific field
by_title = sorted(posts, key=lambda p: p["title"])
by_views = sorted(posts, key=lambda p: p["views"], reverse=True) # descending
by_created = sorted(posts, key=lambda p: p["created"])
# Multiple sort criteria (sort by views desc, then title asc)
by_multi = sorted(posts, key=lambda p: (-p["views"], p["title"]))
# Sort strings case-insensitively
names = ["Charlie", "alice", "Bob"]
sorted(names, key=str.lower) # ["alice", "Bob", "Charlie"]
# str.lower is a method reference โ equivalent to lambda s: s.lower()
# min() and max() with key
most_popular = max(posts, key=lambda p: p["views"])
print(most_popular["title"]) # A Post
map() and filter()
numbers = [1, 2, 3, 4, 5, 6]
# map(function, iterable) โ applies function to every item
# Returns a map object (lazy) โ convert to list if needed
squares = list(map(lambda n: n ** 2, numbers))
# [1, 4, 9, 16, 25, 36]
# Same with list comprehension (usually preferred)
squares2 = [n ** 2 for n in numbers] # โ more Pythonic
# filter(function, iterable) โ keeps items where function returns True
evens = list(filter(lambda n: n % 2 == 0, numbers))
# [2, 4, 6]
# Same with list comprehension (usually preferred)
evens2 = [n for n in numbers if n % 2 == 0] # โ more Pythonic
# map with a named function
def format_price(price):
return f"${price:.2f}"
prices = [19.99, 5.50, 100.0]
formatted = list(map(format_price, prices))
# ["$19.99", "$5.50", "$100.00"]
# FastAPI use: transform DB rows to response format
def row_to_response(row):
return {"id": row.id, "title": row.title, "slug": row.slug}
response_data = list(map(row_to_response, db_rows))
Functions as Arguments โ Higher-Order Functions
# A higher-order function takes a function as an argument or returns one
# Built-in higher-order functions: sorted, map, filter, max, min, any, all
# any() โ True if at least one item is truthy
has_admin = any(u["role"] == "admin" for u in users)
# all() โ True only if ALL items are truthy
all_published = all(p["published"] for p in posts)
# Custom higher-order function
def apply_to_all(items, func):
return [func(item) for item in items]
def double(n): return n * 2
apply_to_all([1, 2, 3], double) # [2, 4, 6]
apply_to_all(["a", "b"], str.upper) # ["A", "B"]
apply_to_all([1, 2, 3], lambda n: n**3) # [1, 8, 27]
# Function factories (return a function)
def make_validator(min_len, max_len):
def validate(text):
return min_len <= len(text) <= max_len
return validate
validate_username = make_validator(3, 20)
validate_bio = make_validator(0, 500)
print(validate_username("Al")) # False (too short)
print(validate_username("Alice")) # True
print(validate_bio("Hello world")) # True
Common Mistakes
Mistake 1 โ Using lambda when a named function is clearer
โ Wrong โ complex lambda is hard to read:
result = sorted(posts, key=lambda p: (p["published"], -p["views"], p["title"].lower()))
โ Correct โ named function with a docstring explains intent:
def sort_key(post):
return (post["published"], -post["views"], post["title"].lower())
result = sorted(posts, key=sort_key) # โ readable
Mistake 2 โ Forgetting map() and filter() return lazy objects
โ Wrong โ comparing lazy object to a list:
result = map(lambda n: n*2, [1, 2, 3])
print(result == [2, 4, 6]) # False โ result is a map object, not a list
โ Correct โ convert to list first:
result = list(map(lambda n: n*2, [1, 2, 3]))
print(result == [2, 4, 6]) # True โ
Mistake 3 โ Using lambda instead of operator module
โ Wrong โ lambda wrapping a simple operator:
from functools import reduce
product = reduce(lambda a, b: a * b, [1, 2, 3, 4]) # works but verbose
โ Correct โ use operator module for common operations:
import operator
product = reduce(operator.mul, [1, 2, 3, 4]) # โ cleaner
Quick Reference
| Pattern | Code |
|---|---|
| Simple lambda | lambda x: x * 2 |
| Lambda with ternary | lambda x: "yes" if x else "no" |
| Sort by field | sorted(items, key=lambda x: x["field"]) |
| Sort descending | sorted(items, key=lambda x: x["n"], reverse=True) |
| Transform all items | list(map(func, items)) |
| Filter items | list(filter(func, items)) |
| Any truthy | any(cond for item in items) |
| All truthy | all(cond for item in items) |