카테고리 없음

[Python] 데코레이터 decorator

kinggoddino 2024. 11. 26.

🐍 데코레이터

  • 이름 그대로 파이썬의 함수를 장식해주는 역할
  • 데코레이터는 선언되는 함수 위에 @를 사용해 @decorator 형태로 작성함
  • 해당 함수가 실행될 때 데코레이터에서 선언 된 코드가 같이 실행된다

 

 

🐍 데코레이터 코드 구조

# 데코레이터는 호출 할 함수를 인자로 받도록 선언합니다.
def decorator(func):
    # 호출 할 함수를 감싸는 wrapper 함수를 선언합니다.
    def wrapper():
        # func.__name__에는 데코레이터를 호출 한 함수의 이름이 들어갑니다.
        print(f"{func.__name__} 함수에서 데코레이터 호출")
        func()
        print(f"{func.__name__} 함수에서 데코레이터 끝")

    # wrapper 함수를 리턴합니다.
    return wrapper

1. 데코레이터로 사용할 함수를 선언

- func을 인자로 받는다

- 함수 안에 함수가 있는 구조임

- 호출할 함수를 감싸주는 wrapper 함수 선언

@decorator
def decorator_func():
    print("decorator_func 함수 호출")

decorator_func()

# result output
"""
decorator_func 함수에서 데코레이터 호출
decorator_func 함수 호출
decorator_func 함수에서 데코레이터 끝
"""

2. 선언되는 함수 위에 @decorator를 추가해 데코레이터를 사용 가능

- @ 뒤에 오는 이름은 내가 선언한 데코레이터 함수 이름을 의미함

- 1번에서 "decorator" 라는 이름으로 함수를 만들었기 때문에 @decorator

 

 

정리

데코레이터 함수를 정의한 이후에는 @decorator 형태를 사용해서

특정 함수가 실행될 때, 데코레이터를 같이 실행해줄 수 있다

또는 함수가 실행되기 전, 후에 내가 원하는 코드를 실행 할 수 있음

 

 

 

🐍 데코레이터 예제

내가 실행하는 함수의 실행 시간이 얼마나 걸렸는지 확인하는 코드

# 특정 함수의 실행 시간 구하기
import time
import random

def time_checker(func):
    def wrapper():
        # 함수가 실행될 때 시간을 저장
        start_time = time.time()

        # 함수를 실행
        func()

        # 함수가 종료된 후 시간에 실행될 때 시간을 빼 실행 시간을 구함
        executed_time = time.time() - start_time

        # 실행 시간을 소수점 5자리까지만 출력
        print(f"{func.__name__} 함수의 실행시간 : {executed_time:.05f}s")

    return wrapper

@time_checker
def main():
    # 함수의 실행 시간을 테스트하기 위해 0.1초 ~ 1초간 sleep
    time.sleep(random.randint(1, 10) / 10)

for i in range(10):
    main()

# result output
"""
main 함수의 실행시간 : 0.80095s
main 함수의 실행시간 : 0.90009s
main 함수의 실행시간 : 1.00027s
main 함수의 실행시간 : 0.20020s
main 함수의 실행시간 : 0.90011s
main 함수의 실행시간 : 0.60041s
main 함수의 실행시간 : 0.30027s
main 함수의 실행시간 : 0.40024s
main 함수의 실행시간 : 0.10026s
main 함수의 실행시간 : 0.50032s
"""

 

이런식으로 다양한 활용 가능!

 

ex) 사용자 권한 체크 - 인증된 사용자만 실행가능하도록 만들기

예를 들어 login_required 라는 데코레이터를 만들어서,

사용자가 인증된 사용자인지 체크하는 코드를 넣은 후,

if 문으로 분기하여 인증 여부에 따라 함수 실행 여부를 나누면 된다.

실제로 많이 사용되는 방식임.

 

 

 

🐍 인자가 있는 함수의 데코레이터 예제

wrapper 함수에 인자를 받아준다. 

# 입력받은 인자에 2를 곱해주기
def double_number(func):
    def wrapper(a, b):
        # 함수에서 받은 인자에 2를 곱해준다
        double_a = a * 2
        double_b = b * 2

        return func(double_a, double_b)
    return wrapper


@double_number
def double_number_add(a, b):
    return a + b


def add(a, b):
    return a + b
    
    
print(double_number_add(5, 10))  # 30
print(add(5, 10))                # 15

double_number 데코레이터를 사용할 경우, 각 숫자에 2를 곱해준 값을 기준으로 계산한 결과가 출력되는 것을 확인할 수 있다.

 

이런식으로 함수에 인자가 있을 때도

데코레이터에서 그 인자를 동일하게 받아서 사용할 수 있다

 

그리고

어떤 함수에든 데코레이터를 갖다 붙히기만 하면

내가 원하는 방식으로 코드를 실행할 수 있우