오늘은 테스트 코드를 작성하는 작업을 했는데, 테스트 코드를 작성하는 과정에서 데코레이터를 활용해서 테스트 결과를 출력하는 코드를 짜려고 했다.
그런데, 데코레이터에 대해서 좀 헷갈리는 부분이 있었다. 데코레이터의 사용법 자체는 그리 헷갈리진 않았는데, 데코레이터 함수의 선언 방법이 좀 헷갈렸다.
그래서, 이번 기회에 데코레이터를 정리해 보았다. 헷갈리는 부분을 정리해서 4개의 케이스로 나누고, 약간의 팁을 덧붙여봤다.
| 함수의 매개변수 없음 | 함수의 매개변수 있음 | |
|---|---|---|
| 데코레이터의 매개변수 없음 | 케이스 ① | 케이스 ② |
| 데코레이터의 매개변수 있음 | 케이스 ③ | 케이스 ④ |
def decorator(func):
def wrapper():
func()
# 데코레이터 로직
return wrapper
@decorator
def func():
pass
아래와 같은 의미를 가지게 됨
func = decorator(func)
decorator(func): decorator 함수를 func 인자 전달하여 호출decorator 함수가 wrapper를 반환, func = wrapperwrapper 함수에서 func 호출 (func()) 및 데코레이터 로직 수행def decorator(func):
def wrapper(*func_args, **func_kwargs):
func(*func_args, **func_kwargs)
# 데코레이터 로직
return wrapper
@decorator
def func(*func_args, **func_kwargs):
pass
데코레이터로 만들어진 함수는 아래와 같은 의미를 가지게 됨
func = decorator(func)
decorator(func): decorator 함수를 func 인자 전달하여 호출decorator 함수가 wrapper를 반환, func = wrapperwrapper 함수에서 *func_args, **func_kwargs 인자 전달하여 func 호출 (func(*func_args, **func_kwargs)) 및 데코레이터 로직 수행def decorator_factory(*deco_args, **deco_kwargs):
def decorator(func):
def wrapper():
func()
# 데코레이터 로직
return wrapper
return decorator
@decorator_factory(*deco_args, **deco_kwargs)
def func():
pass
데코레이터로 만들어진 함수는 아래와 같은 의미를 가지게 됨
func = decorator_factory(*deco_args, **deco_kwargs)(func)
decorator_factory(*deco_args, **deco_kwargs): decorator_factory 함수를 *deco_args, **deco_kwargs 인자 전달하여 호출decorator_factory 함수가 decorator를 반환, func = decorator(func)decorator(func): decorator 함수를 func 인자 전달하여 호출decorator 함수가 wrapper를 반환, func = wrapperwrapper 함수에서 func 호출 (func()) 및 데코레이터 로직 수행def decorator_factory(*deco_args, **deco_kwargs):
def decorator(func):
def wrapper(*func_args, **func_kwargs):
func(*func_args, **func_kwargs)
# 데코레이터 로직
return wrapper
return decorator
@decorator_factory(*deco_args, **deco_kwargs)
def func(*func_args, **func_kwargs):
pass
데코레이터로 만들어진 함수는 아래와 같은 의미를 가지게 됨
func = decorator_factory(*deco_args, **deco_kwargs)(func)
decorator_factory(*deco_args, **deco_kwargs): decorator_factory 함수를 *deco_args, **deco_kwargs 인자 전달하여 호출decorator_factory 함수가 decorator를 반환, func = decorator(func)decorator(func): decorator 함수를 func 인자 전달하여 호출decorator 함수가 wrapper를 반환, func = wrapperwrapper 함수에서 *func_args, **func_kwargs 인자 전달하여 func 호출 (func(*func_args, **func_kwargs)) 및 데코레이터 로직 수행unittest 테스트 메소드에서 성공 메시지 출력def print_test_success_message(test_description: str):
def decorator(func):
def wrapper(testcase_instance):
func(testcase_instance)
print(f"테스트 성공! 테스트 내용: {test_description}")
return wrapper
return decorator
class MyTestCase(unittest.TestCase):
@print_test_success_message("something")
def test_something(self):
# 테스트 코드 작성
decorator -> wrapper)func = decorator(func)decorator_factory -> decorator -> wrapper)func = decorator_factory(*deco_args, **deco_kwargs)(func)decorator_factory: 데코레이터의 인자를 매개변수로 취함decorator: 함수 객체(callable)를 매개변수로 취함wrapper: 함수의 인자를 매개변수로 취함