First-Class Functions in Python
In Python, functions are first-class citizens—they behave like other data types (e.g., int, str). This means you can:
- Assign functions to variables.
- Pass functions as arguments to other functions.
- Store functions in data structures (e.g., dictionaries, lists).
- Returnn functions from other functions.
Treating Functions as Objects
Since types like str, list, and int are objects, Python functions are also objects. For example:
def greet(): # Define a function
print("Hello!")
# Assign the function to a variable
greeting_func = greet
# Call the function via the variable
greeting_func() # Prints: Hello!
The line greeting_func = greet assigns the function object (referenced by greet) to greeting_func.
Callable Objects
Objects can act like functions if they implement the __call__ method. Example:
class GreetingMaker:
def __init__(self, greeting_text):
self.text = greeting_text
def __call__(self, name):
return f"{self.text}, {name}!"
# Create a callable instance
morning_greet = GreetingMaker("Good morning")
print(morning_greet("Alice")) # Output: Good morning, Alice!
Use callable() to check if an object can be called:
print(callable(morning_greet)) # True (object is callable)
print(callable(42)) # False (integers aren’t callable)
Storing Functions in Data Structures
Functions can be stored in dictionaries, lists, etc. This is useful for mapping inputs to actions:
def action_0():
print("Performing action 0")
def action_1():
print("Performing action 1")
# Store functions in a dictionary
action_map = {
0: action_0,
1: action_1
}
# Retrieve and call a function
task = int(input("Enter 0 or 1: "))
action_map[task]() # Calls the selected function
Higher-Order Functions (Functions as Arguments/Return Values)
A higher-order functon accepts a functon as input or returns a function. They enable abstracting over actions.
Example: Abstracting Iteration
Instead of hardcoding an operation, use a higher-order function:
def process_list(items, operation):
for item in items:
operation(item)
# Example 1: Print each item
process_list([1, 2, 3], print) # Prints 1, 2, 3
# Example 2: Square each item (using a lambda)
process_list([1, 2, 3], lambda x: print(x ** 2)) # Prints 1, 4, 9
Returning Functions
Functions can return other functions (e.g., a "calculator factory"):
def create_calculator(operation):
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def multiply(a, b):
return a * b
if operation == "add":
return add
elif operation == "subtract":
return subtract
else:
return multiply
# Create an addition calculator
adder = create_calculator("add")
print(adder(5, 3)) # 8
# Create a multiplication calculator
multiplier = create_calculator("multiply")
print(multiplier(5, 3)) # 15
Nested Functions (Inner Functions)
Functions can be defined inside other functions (inner functions) to create helpers:
def fibonacci(n):
def fib_helper(a, b, current):
if current == n:
return b
return fib_helper(b, a + b, current + 1)
if n <= 1:
return n
return fib_helper(0, 1, 1)
print(fibonacci(10)) # Output: 55
Lambda Expressions (Anonymous Functions)
Lambda expressions create short, anonymous functions. Use them for one-time or inline operations:
# Define a lambda for multiplication
mult = lambda a, b: a * b
print(mult(2, 3)) # 6
# Use a lambda immediately (anonymous)
result = (lambda x, y: x + y)(5, 3)
print(result) # 8
Map, Filter, and Reduce
These functions transform or process iterables:
Map
map() applies a function to every element in an iterable. Example:
numbers = [1, 2, 3, 4]
squared = list(map(lambda x: x ** 2, numbers))
print(squared) # [1, 4, 9, 16]
Filter
filter() selects elements that satisfy a condition. Example (extract even numbers):
numbers = [1, 2, 3, 4, 5]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [2, 4]
Reduce
reduce() (from functools) aggregates elements into a single value. Example (sum a list):
from functools import reduce
numbers = [1, 2, 3, 4]
total = reduce(lambda a, b: a + b, numbers)
print(total) # 10
These techniques empower Python developers to write concise, reusable, and expressive code—core principles of functional programming.