Lambda Functions
Lambda functions, also known as anonymous functions, are small, unnamed functions defined with the lambda
keyword. They provide a concise way to create simple functions without the need for a formal function definition using def
.
Basic Syntax
The syntax for a lambda function is:
lambda arguments: expression
A lambda function can take any number of arguments but can only have one expression. The expression is evaluated and returned when the function is called.
# Regular function definition
def add(x, y):
return x + y
# Equivalent lambda function
add_lambda = lambda x, y: x + y
# Both functions work the same way
print(add(5, 3)) # Output: 8
print(add_lambda(5, 3)) # Output: 8
Important: Lambda functions are limited to a single expression. They cannot contain multiple statements or complex logic that would require multiple lines of code.
When to Use Lambda Functions
Lambda functions are most useful in situations where:
- You need a simple function for a short period
- You want to pass a function as an argument to another function
- You need to define a function inside another function
Lambda functions are commonly used with higher-order functions like map()
, filter()
, and sorted()
.
Lambda with map()
The map()
function applies a function to each item in an iterable (like a list).
# Using a regular function with map()
def square(x):
return x ** 2
numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(square, numbers))
print(squared_numbers) # Output: [1, 4, 9, 16, 25]
# Using a lambda function with map()
squared_numbers_lambda = list(map(lambda x: x ** 2, numbers))
print(squared_numbers_lambda) # Output: [1, 4, 9, 16, 25]
In this example, the lambda function lambda x: x ** 2
is applied to each element in the numbers
list, creating a new list with the squared values.
Lambda with filter()
The filter()
function creates a new iterable with elements from the original iterable for which a function returns True
.
# Using a regular function with filter()
def is_even(x):
return x % 2 == 0
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(is_even, numbers))
print(even_numbers) # Output: [2, 4, 6, 8, 10]
# Using a lambda function with filter()
even_numbers_lambda = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers_lambda) # Output: [2, 4, 6, 8, 10]
Here, the lambda function lambda x: x % 2 == 0
tests each element in the numbers
list and keeps only those that are even.
Lambda with sorted()
The sorted()
function returns a new sorted list from the elements of any iterable. You can use a lambda function as the key
parameter to customize the sorting logic.
# List of tuples (name, age)
people = [
("Alice", 25),
("Bob", 19),
("Charlie", 32),
("David", 27)
]
# Sort by name (first element in each tuple)
sorted_by_name = sorted(people)
print(sorted_by_name) # Sorts by the first element by default
# Sort by age (second element in each tuple) using lambda
sorted_by_age = sorted(people, key=lambda person: person[1])
print(sorted_by_age)
# Sort by name length using lambda
sorted_by_name_length = sorted(people, key=lambda person: len(person[0]))
print(sorted_by_name_length)
In this example, we’re using lambda functions to specify which part of the tuple should be used for sorting.
Lambda with reduce()
The reduce()
function (from the functools
module) applies a function of two arguments cumulatively to the items of an iterable, reducing it to a single value.
from functools import reduce
# Calculate the product of all numbers in a list
numbers = [1, 2, 3, 4, 5]
# Using a regular function
def multiply(x, y):
return x * y
product = reduce(multiply, numbers)
print(product) # Output: 120 (1*2*3*4*5)
# Using a lambda function
product_lambda = reduce(lambda x, y: x * y, numbers)
print(product_lambda) # Output: 120
The lambda function lambda x, y: x * y
takes two arguments and multiplies them together. The reduce()
function applies this lambda to the first two elements of the list, then to the result and the next element, and so on.
Multiple Arguments in Lambda Functions
Lambda functions can take multiple arguments:
# Lambda function with two arguments
multiply = lambda x, y: x * y
print(multiply(5, 3)) # Output: 15
# Lambda function with three arguments
calculate = lambda x, y, z: x + y * z
print(calculate(2, 3, 4)) # Output: 14 (2 + 3*4)
Default Arguments in Lambda Functions
Lambda functions can also have default arguments:
# Lambda with a default argument
greet = lambda name, greeting="Hello": f"{greeting}, {name}!"
print(greet("Alice")) # Output: Hello, Alice!
print(greet("Bob", "Hi")) # Output: Hi, Bob!
Lambda Functions as Return Values
You can return lambda functions from other functions:
def power_function(n):
return lambda x: x ** n
square = power_function(2)
cube = power_function(3)
fourth_power = power_function(4)
print(square(5)) # Output: 25 (5^2)
print(cube(5)) # Output: 125 (5^3)
print(fourth_power(5)) # Output: 625 (5^4)
In this example, power_function()
returns a lambda function that raises its argument to the power of n
. We create three different functions for squaring, cubing, and raising to the fourth power.
Immediately Invoked Lambda Functions
You can define and call a lambda function in one step:
# Define and call in one step
result = (lambda x, y: x + y)(5, 3)
print(result) # Output: 8
This pattern is less common in Python than in some other languages, but it can be useful in specific situations.
Lambda Functions with Conditional Expressions
Lambda functions can include conditional expressions:
# Lambda with a conditional expression
is_adult = lambda age: "Adult" if age >= 18 else "Minor"
print(is_adult(20)) # Output: Adult
print(is_adult(15)) # Output: Minor
# More complex conditional
grade = lambda score: "A" if score >= 90 else ("B" if score >= 80 else ("C" if score >= 70 else ("D" if score >= 60 else "F")))
print(grade(95)) # Output: A
print(grade(85)) # Output: B
print(grade(60)) # Output: D
Note: While you can include conditional expressions in lambda functions, they should remain simple. If the logic becomes complex, it’s better to use a regular function with proper if-else statements for readability.
Practical Examples of Lambda Functions
Example 1: Custom Sorting
Sort a list of dictionaries by a specific key:
# List of student dictionaries
students = [
{"name": "Alice", "grade": 85},
{"name": "Bob", "grade": 92},
{"name": "Charlie", "grade": 78},
{"name": "David", "grade": 87}
]
# Sort by grade (highest to lowest)
sorted_by_grade = sorted(students, key=lambda student: student["grade"], reverse=True)
print("Students sorted by grade (highest to lowest):")
for student in sorted_by_grade:
print(f"{student['name']}: {student['grade']}")
Example 2: Data Transformation
Transform a list of data:
# List of temperatures in Celsius
celsius_temps = [20, 25, 30, 35, 40]
# Convert to Fahrenheit using map with lambda
fahrenheit_temps = list(map(lambda c: (c * 9/5) + 32, celsius_temps))
print("Celsius temperatures:", celsius_temps)
print("Fahrenheit temperatures:", fahrenheit_temps)
Example 3: Filtering Data Based on Multiple Conditions
Filter items based on complex conditions:
# List of products
products = [
{"name": "Laptop", "price": 1200, "in_stock": True},
{"name": "Smartphone", "price": 800, "in_stock": True},
{"name": "Tablet", "price": 500, "in_stock": False},
{"name": "Headphones", "price": 150, "in_stock": True},
{"name": "Monitor", "price": 300, "in_stock": False}
]
# Filter products: in stock and price under 1000
available_affordable = list(filter(
lambda product: product["in_stock"] and product["price"] < 1000,
products
))
print("Available and affordable products:")
for product in available_affordable:
print(f"{product['name']} - ${product['price']}")
Example 4: Creating Function Factories
Create customized functions dynamically:
def price_calculator(tax_rate):
"""Returns a function that calculates the price after tax."""
return lambda price: price * (1 + tax_rate)
# Create tax calculators for different regions
calculate_price_ca = price_calculator(0.0725) # 7.25% tax in California
calculate_price_ny = price_calculator(0.0845) # 8.45% tax in New York
# Test the calculators
product_price = 100.00
print(f"Product base price: ${product_price}")
print(f"Price in California: ${calculate_price_ca(product_price):.2f}")
print(f"Price in New York: ${calculate_price_ny(product_price):.2f}")
Advantages of Lambda Functions
- Conciseness: Lambda functions allow you to write small functions in a compact way.
- Readability: For simple operations, lambdas can make code more readable by keeping the function definition close to where it’s used.
- Functional Programming: They facilitate functional programming patterns, working well with functions like
map()
,filter()
, andreduce()
.
Limitations of Lambda Functions
- Single Expression Only: Lambda functions are restricted to a single expression, making them unsuitable for complex logic.
- No Docstrings: You cannot include documentation within lambda functions.
- Limited Debugging: Debugging lambda functions can be more difficult than regular functions.
- May Reduce Readability: For anything beyond simple operations, regular functions with descriptive names are often more clear.
Important:
Lambda functions are best used for simple, short operations. For complex logic or functions that will be reused throughout your code, regular function definitions with the def
keyword are more appropriate.
Lambda Functions vs. Regular Functions
Feature | Lambda Functions | Regular Functions |
---|---|---|
Syntax | lambda args: expression | def name(args): body |
Named | No (anonymous) | Yes (has a name) |
Number of expressions | One only | Multiple |
Docstrings | Not supported | Supported |
Return statement | Implicit (expression value) | Explicit (using return ) |
Complexity | Simple operations | Any complexity |
# Lambda function
addition = lambda x, y: x + y
# Equivalent regular function
def addition(x, y):
"""Add two numbers and return the result."""
return x + y
Best Practices for Using Lambda Functions
Keep It Simple: Use lambdas only for simple, one-line functions.
# Good square = lambda x: x ** 2 # Bad (too complex for a lambda) complex_lambda = lambda x: x ** 2 if x > 0 else "negative" if x < 0 else "zero"
Assign to a Variable When Reused: If you need to use the same lambda multiple times, assign it to a variable.
# Reusable lambda is_even = lambda x: x % 2 == 0 numbers = [1, 2, 3, 4, 5, 6] even_numbers = list(filter(is_even, numbers))
Consider Regular Functions for Clarity: When a lambda becomes complex or needs documentation, use a regular function.
# Better as a regular function def calculate_tax(price, tax_rate): """Calculate the price after tax.""" return price * (1 + tax_rate)
Use with Higher-Order Functions: Lambdas shine when used with functions like
map()
,filter()
,sorted()
, etc.names = ["Alice", "Bob", "Charlie", "David"] sorted_names = sorted(names, key=lambda name: len(name))
Common Mistakes with Lambda Functions
Trying to Include Multiple Statements:
# This will not work invalid_lambda = lambda x: print(x); return x * 2 # Use a regular function instead def process(x): print(x) return x * 2
Making Lambdas Too Complex:
# Too complex for a lambda complex_lambda = lambda x: (x ** 2 if x % 2 == 0 else x ** 3) if x >= 0 else -x # Better as a regular function def compute(x): if x < 0: return -x elif x % 2 == 0: return x ** 2 else: return x ** 3
Not Understanding Closure Behavior:
# This creates a common mistake in loops functions = [] for i in range(5): functions.append(lambda: i) # All functions will use the final value of i for f in functions: print(f()) # Prints 4, 4, 4, 4, 4 # Correct approach using default arguments functions = [] for i in range(5): functions.append(lambda i=i: i) for f in functions: print(f()) # Prints 0, 1, 2, 3, 4
Exercises
Exercise 1: Write a lambda function that takes a string and returns its length. Use this function with map()
to get the lengths of all strings in a list.
strings = ["apple", "banana", "cherry", "date", "elderberry"]
# Your code here
Exercise 2: Create a lambda function that checks if a number is between 10 and 20 (inclusive). Use this function with filter()
to get all numbers in that range from a list.
numbers = [5, 10, 15, 20, 25, 30]
# Your code here
Exercise 3: Write a function that returns a lambda function. The returned lambda should multiply its input by a value specified when creating the function.
# Your function definition here
# Test with:
double = # Create a function that doubles the input
triple = # Create a function that triples the input
print(double(5)) # Should print 10
print(triple(5)) # Should print 15
Exercise 4: Use a lambda function as the key parameter in sorted()
to sort a list of tuples representing people (name, age, height) by:
a) Age (youngest to oldest)
b) Height (tallest to shortest)
c) Name length (shortest to longest)
people = [
("Alice", 25, 165),
("Bob", 19, 180),
("Charlie", 32, 175),
("David", 27, 190)
]
# Your sorting code here
Hint for Exercise 1: The lambda function will take a parameter s
and return len(s)
. Use this with map()
to get a list of lengths.
# Exercise 1 partial solution
length_lambda = lambda s: len(s)
lengths = list(map(length_lambda, strings))
In the next section, we’ll explore modules and packages in Python, which allow you to organize and reuse code effectively.