Higher-Order Patterns
Functions are first-class citizens in Python. You can pass them around, return them, and compose them to build expressive APIs.
First-Class Functions
def shout(text):
return text.upper()
def whisper(text):
return text.lower()
def speak(style, message):
return style(message)
print(speak(shout, "hello"))
Passing Callbacks
def apply_and_log(func, value):
result = func(value)
print(f"Result: {result}")
return result
apply_and_log(lambda x: x ** 2, 5)
Lambdas provide inline anonymous functions but are limited to single expressions. Use def
for multi-line logic.
Returning Functions
def power(exp):
def raise_to(base):
return base ** exp
return raise_to
square = power(2)
print(square(7))
Decorators
Decorators wrap functions with additional behaviour.
def trace(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
@trace
def greet(name):
return f"Hello, {name}!"
⚠️
Always preserve metadata on decorated functions using functools.wraps
. Without it, docstrings and names are lost.
from functools import wraps
def trace(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
Partial Functions
functools.partial
pre-fills parameters to create specialised callables.
from functools import partial
send_email = partial(print, "Sending email to")
send_email("team@pythonforall.com")
Function Composition
Combine simple functions for powerful pipelines.
def compose(f, g):
def inner(x):
return f(g(x))
return inner
strip_and_lower = compose(str.lower, str.strip)
print(strip_and_lower(" HELLO "))
Functional Utilities
map(func, iterable)
appliesfunc
lazily.filter(func, iterable)
keeps items wherefunc(item)
is truthy.functools.reduce(func, iterable, initial)
folds values into a single result.
from functools import reduce
nums = [1, 2, 3, 4]
product = reduce(lambda a, b: a * b, nums, 1)
Higher-Order Practice
Pyground
Create a decorator that times a function and prints the duration before returning the result.
Output:
Higher-order patterns keep code DRY by extracting cross-cutting concerns such as logging, caching, and timing into reusable decorators.