python

Python | Python 데코레이터(Decorator)

no-easy-ray 2022. 1. 26. 18:02

파이썬의 데코레이터에 대해서 정리합니다.

 

파이썬의 웹 프레임워크나 라이브러리들을 사용할 때 @로 시작하는 것을 확인할 수 있습니다.

이를 파이썬에서는 데코레이터라고 합니다.

데코레이터(Decorator)는 기존 함수의 변경 없이 추가적인 기능을 덧붙일 수 있도록 해 주는 함수라고 보시면 됩니다.

 

간단하게 메서드의 시간을 측정하는 기능을 하는 데코레이터를 만들어 보면서 데코레이터가 어떤 것인지 정리해보도록 하겠습니다.

데코레이터는 함수와 클래스 둘 다 이용하여 만들 수 있습니다.

 

데코레이터(함수)

from time import sleep, perf_counter

def time_check_func(func):
    def check(*args):
        start = perf_counter()
        func(*args) # 받아온 함수 실행!
        end = perf_counter()
        print(f'>> {start} / {end} / {end - start}')

    return check

다음과 같이 데코레이터는 함수를 매개변수로 받아서 내부의 함수에서 실행하는 구조로 되어있습니다.

 

위와 같은 함수를 이용해서 시간을 측정한다고 했을 경우 다음과 같이 할 수 있습니다.

# 테스트 함수
def test_decorator_func(*args):
    print(f'run function decorator >> {args}')
    sleep(1)

time_check_func(test_decorator_func)('A','B','C','D')
# run function decorator >> ('A', 'B', 'C', 'D')
# >> 290215.2574023 / 290216.2585761 / 1.0011737999739125

다음과 같이 time_check_func이라는 함수에 매개변수로 test_decorator_func을 넣고 time_check_func내부의 check를 이용하여 호출하게 되는 것인데, 너무 코드가 길어지고 복잡해집니다.

 

이때 데코레이터를 이용하면 쉽게 사용할 수 있습니다.

@time_check_func
def test_decorator_func(*args):
    print(f'run function decorator >> {args}')
    sleep(1)

test_decorator_func('A','B','C','D')
# run function decorator >> ('A', 'B', 'C', 'D')
# >> 290215.2574023 / 290216.2585761 / 1.0011737999739125

@time_check_func
def other_func():
    print('other function run')
    sleep(2)

other_func()
# other function run
# >> 290877.8528502 / 290879.8550702 / 2.002219999965746

테스트 함수 위에 @time_check_func를 작성하게 되면 이전에 사용한 것처럼 동작하게 됩니다.

또한 다른 함수들에도 데코레이터를 재사용함으로써 시간을 측정하는 기능을 손쉽게 적용할 수 있습니다.

 

데코레이터(클래스)

class time_check_cls:
    def __init__(self, func):
        self._func = func

    def __call__(self):
        start = perf_counter()
        self._func()
        end = perf_counter()
        print(f'>> {start} / {end} / {end - start}')

클래스 형태로 데코레이터를 작성할 경우 init 메서드에 매개변수로 func을 받도록 하고,

call 메서드를 구현함으로써 생성할 수 있습니다.

 

사용은 함수로 만든 경우와 동일하게 사용할 수 있습니다.

@time_check_cls
def test_decorator_cls():
    print('run class decorator')
    sleep(1)

test_decorator_cls()
# run class decorator
# >> 290879.8553817 / 290880.8566954 / 1.00131370004965

 

마무리

파이썬 데코레이터에 대해서 정리해보는 시간이었습니다.

파이썬에서는 데코레이터가 자주 사용되는 것을 확인할 수 있었습니다. Flask의 @route부터 시작해서 pythontips에서 예시로 제공한 인증처리 등 앞으로 파이썬으로 코딩을 하면서 데코레이터를 제대로 활용할 수 있으면 많은 도움이 될 것 같은 생각이 들었습니다.

 

감사합니다.

 

참고자료

https://book.pythontips.com/en/latest/decorators.html#giving-a-function-as-an-argument-to-another-function

https://dojang.io/mod/page/view.php?id=2427