Python:Decorator
lastmod 2025-01-09created 2015-12-029 edits
How to make a decorator that accepts parameters
When making a decorator that accepts parameters in Python, you usually need three levels of functions:
- The decorator factory function
- The actual decorator function
- And the wrapped function.
Recommended symbol names for each function are as follows:
def decorator_with_params(param1, param2):
# 1. 데코레이터 생성 함수
def decorator(func):
# 2. 실제 데코레이터 함수
def wrapper(*args, **kwargs):
# 3. 래핑된 함수
print(f"데코레이터 파라미터: {param1}, {param2}")
print(f"함수 {func.__name__} 호출 전")
result = func(*args, **kwargs)
print(f"함수 {func.__name__} 호출 후")
return result
return wrapper
return decorator
Symbol naming guidelines
- Top-level function (factory function that takes the parameters):
- Names: decorator_with_params, create_decorator, decorator_factory, param_decorator
- Role: takes the parameters that define how the decorator behaves.
- Names: decorator, inner_decorator, wrap_function
- Role: takes the function the decorator is applied to and defines the wrapping logic inside.
- Names: wrapper, wrapped_func, decorated_func, inner_wrapper
- Role: runs extra behavior before/after calling the actual function.
def param_decorator(param1, param2):
def wrap_function(func):
def inner_wrapper(*args, **kwargs):
print(f"[DEBUG] Params: {param1}, {param2}")
print(f"[DEBUG] Before calling {func.__name__}")
result = func(*args, **kwargs)
print(f"[DEBUG] After calling {func.__name__}")
return result
return inner_wrapper
return wrap_function
# 데코레이터 사용
@param_decorator("Hello", "World")
def example_function(x, y):
print(f"Running example_function with {x} and {y}")
return x + y
# 함수 호출
result = example_function(10, 20)
print(f"Result: {result}")
Simple example
def measure_time(f):
def wrap(*args):
time1 = time.time()
ret = f(*args)
time2 = time.time()
print('%s function took %0.6f s' % (f.__name__, (time2-time1)))
return ret
return wrap
# ...
@measure_time
def test(a):
print('haha')
Decorators with Arguments
Needs to be checked whether it works.
def parametrized(dec):
def layer(*args, **kwargs):
def deco(f):
return dec(f, *args, **kwargs)
return deco
return layer
@parametrized
def elapsed_time_debug(func, name, logger):
def wrap(*args, **kwargs):
s = time.time()
func(*args, **kwargs)
e = time.time()
if logger:
logger.debug("[{}] {} detect time: {}".format(name, func.__name__, e-s))
return wrap
Documentation
You should use wraps from the functools package.
from functools import wraps
# 파라메터 없는 데코레이터에도 @wraps 붙여주고
def decorator(func):
@wraps(func)
def decorator(*args, **kwargs):
print("%s %s" % (func.__name__, "before"))
result = func(*args, **kwargs)
print("%s %s" % (func.__name__, "after"))
return result
return decorator
# 파라메터 있는 데코레이터에도 @wraps 붙여주고
def decorator_with_param(param):
def wrapper(func):
@wraps(func)
def decorator(*args, **kwargs):
print(param)
print("%s %s" % (func.__name__, "before"))
result = func(*args, **kwargs)
print("%s %s" % (func.__name__ , "after"))
return result
return decorator
return wrapper
See also
Favorite site
- Python decorators: the basics
- [Recommended] Python - Decorator 1
- Python — How to write a decorator
- [Recommended] Writing a Python decorator that can be called as a function or a callable
References
-
SchoolofWeb_-_Python_Decorator.pdf ↩