Using Python's functools Module to Build Advanced Decorators
This article explains the fundamentals of Python decorators, demonstrates how to leverage the standard library functools module—including wraps, partial, and lru_cache—to build advanced, flexible decorators, and provides concrete timer and partial-function examples with full source code.
We explore the basic concepts of decorators, their purposes, and implementation methods, then dive into using Python's functools module to create more powerful and flexible decorators, highlighting the module's importance and offering practical examples.
functools Module Overview
functools is a standard library module that provides higher‑order functions and utilities for working with callable objects such as functions and methods. Its most commonly used features include:
wraps : preserves the metadata of the decorated function.
partial : creates a new function with some arguments pre‑filled.
lru_cache : caches function results to improve performance.
When building custom decorators, wraps is especially useful because it ensures that the original function’s name, docstring, and other metadata are retained.
Creating Custom Decorators with functools
Below we demonstrate how to use the functools module to create a decorator that measures a function’s execution time.
Example: Timer Decorator
First, we define a decorator that records the start and end times of a function call:
<code>import time
from functools import wraps
def timer_decorator(func):
@wraps(func) # 保持函数的元数据
def wrapper(*args, **kwargs):
start_time = time.time() # 开始计时
result = func(*args, **kwargs) # 执行原函数
end_time = time.time() # 停止计时
print(f"Function '{func.__name__}' executed in {end_time - start_time:.4f} seconds.")
return result
return wrapper
@timer_decorator
def example_function(n):
total = 0
for i in range(n):
total += i
return total
result = example_function(1000000)
print(f"Result: {result}")
</code>Code Explanation
The timer_decorator works as follows:
Inside the wrapper function, time.time() records the start time.
The original function is called with func(*args, **kwargs) to perform the actual computation.
After execution, time.time() records the end time and the elapsed time is calculated.
The decorator prints the execution duration and returns the original result.
Another Example: Partial Application Decorator
The functools.partial function can also be used within decorators. Below is a simple demonstration:
<code>from functools import partial
def multiply(factor, number):
return factor * number
multiply_by_two = partial(multiply, 2) # 创建一个新的函数,固定因子为2
print(multiply_by_two(5)) # 输出 10
</code>In this example, partial creates a new function multiply_by_two where the factor argument is fixed at 2; calling multiply_by_two(5) yields 10.
Conclusion
This article has shown how to enhance custom decorators using Python's functools module. By employing wraps , we preserve the original function’s metadata, and with partial we can create partially applied functions, both of which improve code readability and enable more sophisticated functionality.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.