Skip to content
Search

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:

  1. The decorator factory function
  2. The actual decorator function
  3. 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.
  • Middle function (decorator function):
    • Names: decorator, inner_decorator, wrap_function
    • Role: takes the function the decorator is applied to and defines the wrapping logic inside.
  • Inner function (wrapper function):
    • 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

References


  1. SchoolofWeb_-_Python_Decorator.pdf ↩

author Zer0 sitemap