Python: decorators
In short: A decorator is a function that takes another function and returns an extended version. You apply it with @name above the function.
In more detail: It wraps the original function to do something before or after: time it, check access, cache results, log calls.
In Depth
import functools, time
def timing(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = f(*args, **kwargs)
print(f.__name__, time.perf_counter() - start)
return result
return wrapper
@timing
def compute(n): ...- Equivalent:
@timingabovecomputeis the same ascompute = timing(compute). functools.wraps: Preserves name and documentation of the original function. Without it the function looks likewrapper.- With parameters: A decorator with arguments (
@repeat(3)) is a function returning a decorator (one more level of nesting). - Built in and well known:
@staticmethod,@property,@functools.lru_cache, routes in Flask (@app.route),@pytest.fixture. - Classes: Decorators can also extend classes (
@dataclass). - Note: Do not confuse with the design pattern, see decorator pattern.
See also: dataclasses, lambda