Practical Examples of Closures
Memoization
Closures can be used to implement memoization, a technique for caching the results of expensive function calls. Here's an example:
def memoize(func):
cache = {}
def wrapper(*args):
if args in cache:
return cache[args]
else:
result = func(*args)
cache[args] = result
return result
return wrapper
@memoize
def fibonacci(n):
if n <= 1:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(100)) ## Output: 354224848179261915075
In this example, the memoize
function is a closure that creates a cache
dictionary to store the results of previous function calls. The wrapper
function "closes over" the cache
dictionary and uses it to store and retrieve the results of the fibonacci
function.
Partial Function Application
Closures can be used to create partially applied functions, where some arguments are "fixed" and the remaining arguments are passed later. Here's an example:
def add(x, y):
return x + y
add_five = lambda y: add(5, y)
print(add_five(10)) ## Output: 15
In this example, the add_five
function is a closure that "closes over" the x
argument of the add
function, creating a new function that only requires the y
argument.
Decorators
Closures are the foundation for Python's decorator pattern, which allows you to modify the behavior of a function without changing its source code. Here's an example:
def uppercase(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result.upper()
return wrapper
@uppercase
def say_hello(name):
return f"Hello, {name}!"
print(say_hello("LabEx")) ## Output: HELLO, LABEX!
In this example, the uppercase
function is a closure that creates a wrapper
function that "closes over" the func
argument. The wrapper
function is then used to modify the behavior of the say_hello
function.
Event Handlers
Closures can be used to create event handlers that remember the state of the application. Here's an example:
def create_event_handler():
event_count = 0
def handle_event(event_data):
nonlocal event_count
event_count += 1
print(f"Event {event_count}: {event_data}")
return handle_event
event_handler = create_event_handler()
event_handler("Button clicked") ## Output: Event 1: Button clicked
event_handler("Input changed") ## Output: Event 2: Input changed
In this example, the create_event_handler
function is a closure that creates a handle_event
function that "closes over" the event_count
variable. The handle_event
function can be used as an event handler that remembers the number of events that have been handled.