Skip to content
beginner Phase 4 · Python Functional Programming

Lambda Functions

Create anonymous functions with lambda and use them effectively.

30m
0 problems
Topic Progress 0%

Lambda Basics

What is a Lambda?

A lambda is an anonymous (unnamed) function defined in a single expression.

# Regular function
def add(a, b):
    return a + b

# Lambda equivalent
add = lambda a, b: a + b

print(add(2, 3))  # 5

Lambda Syntax

# lambda arguments: expression

# No arguments
greet = lambda: 'Hello!'
print(greet())  # Hello!

# Single argument
double = lambda x: x * 2
print(double(5))  # 10

# Multiple arguments
add = lambda a, b: a + b
print(add(2, 3))  # 5

# Default arguments
power = lambda x, n=2: x ** n
print(power(3))    # 9
print(power(3, 3))  # 27

# *args and **kwargs
custom = lambda *args, **kwargs: (args, kwargs)
print(custom(1, 2, 3, key='value'))
# ((1, 2, 3), {'key': 'value'})

Lambda vs def

# Lambda:
# - Single expression only
# - Anonymous (no name unless assigned)
# - Returns value automatically
# - No type hints
# - No docstring
# - No annotations

# def:
# - Multiple statements allowed
# - Named function
# - Explicit return needed
# - Supports type hints
# - Supports docstring
# - More readable

# ✅ Use lambda for short, simple functions
# ✅ Use def for complex functions

Lambda Use Cases

Sorting with Key Functions

# Sort by length
words = ['banana', 'pie', 'Washington', 'cat']
words.sort(key=lambda w: len(w))
print(words)  # ['pie', 'cat', 'banana', 'Washington']

# Sort by second element
pairs = [(1, 'b'), (3, 'a'), (2, 'c')]
pairs.sort(key=lambda p: p[1])
print(pairs)  # [(3, 'a'), (1, 'b'), (2, 'c')]

# Sort dictionaries by value
users = [
    {'name': 'Alice', 'age': 30},
    {'name': 'Bob', 'age': 25},
    {'name': 'Charlie', 'age': 35}
]
users.sort(key=lambda u: u['age'])
print(users)  # Sorted by age

With map() and filter()

numbers = [1, 2, 3, 4, 5]

# map: transform each element
doubled = list(map(lambda x: x * 2, numbers))
print(doubled)  # [2, 4, 6, 8, 10]

# filter: keep elements that match
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # [2, 4]

# Better with list comprehensions
doubled = [x * 2 for x in numbers]
evens = [x for x in numbers if x % 2 == 0]

As Arguments

# Passing function as argument
def apply(func, value):
    return func(value)

print(apply(lambda x: x ** 2, 5))  # 25
print(apply(lambda x: x.upper(), 'hello'))  # HELLO

# In reduce
from functools import reduce
product = reduce(lambda a, b: a * b, [1, 2, 3, 4, 5])
print(product)  # 120

Conditional Expressions

# Ternary in lambda
is_even = lambda x: 'even' if x % 2 == 0 else 'odd'
print(is_even(4))  # even
print(is_even(5))  # odd

# Absolute value
abs_val = lambda x: x if x >= 0 else -x
print(abs_val(-5))  # 5

# Max of three
max3 = lambda a, b, c: a if a > b and a > c else (b if b > c else c)
print(max3(1, 2, 3))  # 3

Lambda Pitfalls & Best Practices

Common Pitfalls

# ❌ Closure variable binding issue
funcs = [lambda x: x + i for i in range(5)]
results = [f(0) for f in funcs]
print(results)  # [4, 4, 4, 4, 4] - All use i=4!

# ✅ Fix: use default argument
funcs = [lambda x, i=i: x + i for i in range(5)]
results = [f(0) for f in funcs]
print(results)  # [0, 1, 2, 3, 4]

# ❌ Overly complex lambda
complex = lambda x: x ** 2 + 2 * x + 1 if x > 0 else -x ** 2 + 2 * x - 1

# ✅ Use def for complex logic
def complex_func(x):
    if x > 0:
        return x ** 2 + 2 * x + 1
    return -x ** 2 + 2 * x - 1

When to Use Lambda

# ✅ Good use cases:

# 1. Short key functions
sorted(data, key=lambda x: x.lower())

# 2. Quick transformations
list(map(lambda x: x ** 2, numbers))

# 3. Conditional logic in comprehensions
[lambda x: x * 2 if x > 0 else x for x in numbers]

# 4. GUI callbacks (when simple)
button.on_click(lambda: print('Clicked'))

# ❌ Bad use cases:

# 1. Named function needed
process = lambda x: x * 2  # Bad
# Better:
def process(x):
    return x * 2

# 2. Complex logic
complex = lambda x: (x ** 2 + 2 * x + 1 if x > 0 else -x ** 2 + 2 * x - 1)

# 3. Reusable function
add_one = lambda x: x + 1  # Bad if used frequently
# Better:
def add_one(x):
    return x + 1

Debugging Lambdas

# Lambdas are hard to debug
def debug_lambda(func):
    def wrapper(*args, **kwargs):
        print(f'Calling {func.__name__} with {args}, {kwargs}')
        result = func(*args, **kwargs)
        print(f'Result: {result}')
        return result
    return wrapper

# Use for debugging
add = debug_lambda(lambda a, b: a + b)
add(2, 3)
# Calling <lambda> with (2, 3), {}
# Result: 5