Function Timing Decorator
A simple decorator to measure and print the execution time of any function. Useful for quick performance profiling during development.
Use Case
Use this when you want to quickly measure how long a function takes to execute without setting up complex profiling tools. Perfect for identifying slow functions during development.
Code
1import time
2from functools import wraps
3
4def timing_decorator(func):
5 """Decorator that prints the execution time of a function."""
6 @wraps(func)
7 def wrapper(*args, **kwargs):
8 start_time = time.perf_counter()
9 result = func(*args, **kwargs)
10 end_time = time.perf_counter()
11 elapsed_time = end_time - start_time
12 print(f"{func.__name__} took {elapsed_time:.4f} seconds")
13 return result
14 return wrapper
Explanation
The decorator uses time.perf_counter() which provides the highest resolution timer available on the system. It wraps the original function, measures the time before and after execution, and prints the elapsed time.
The @wraps(func) decorator preserves the original function's metadata (name, docstring, etc.).
Parameters/Options
func: The function to be timed- Returns: The decorated function that includes timing
Examples
Example 1: Basic usage
1@timing_decorator
2def slow_function():
3 time.sleep(2)
4 return "Done"
5
6result = slow_function()
Output:
1slow_function took 2.0012 seconds
Example 2: With function arguments
1@timing_decorator
2def process_data(data, multiplier=2):
3 result = [x * multiplier for x in data]
4 return result
5
6output = process_data([1, 2, 3, 4, 5], multiplier=3)
Output:
1process_data took 0.0001 seconds
Example 3: Enhanced version with return value
1import time
2from functools import wraps
3
4def timing_decorator_v2(func):
5 """Enhanced decorator that returns timing info."""
6 @wraps(func)
7 def wrapper(*args, **kwargs):
8 start_time = time.perf_counter()
9 result = func(*args, **kwargs)
10 end_time = time.perf_counter()
11 elapsed_time = end_time - start_time
12
13 # Return both result and timing
14 return {
15 'result': result,
16 'elapsed_time': elapsed_time,
17 'function_name': func.__name__
18 }
19 return wrapper
20
21@timing_decorator_v2
22def calculate(n):
23 return sum(range(n))
24
25output = calculate(1000000)
26print(f"Result: {output['result']}")
27print(f"Time: {output['elapsed_time']:.4f}s")
Notes
For more detailed profiling, consider using:
cProfilemodule for comprehensive profilingline_profilerfor line-by-line profilingmemory_profilerfor memory usage profiling
This decorator is best for quick checks during development, not for production use.
Gotchas/Warnings
- ⚠️ Overhead: The decorator itself adds minimal overhead (~microseconds)
- ⚠️ Nested decorators: Order matters when stacking multiple decorators
- ⚠️ Async functions: This won't work with async functions - use
asynciotiming instead - ⚠️ Production use: Remove or disable timing decorators in production for performance