[Alex] 데이터 장인의 블로그

[Python] 데코레이터(Decorator) 사용하기 본문

Python

[Python] 데코레이터(Decorator) 사용하기

Alex, Yoon 2021. 12. 26. 13:44

함수(메서드)를 장식. -> decorator (장식자) 

class Calc:
    @staticmethod    # 데코레이터
    def add(a, b):
        print(a + b)

클래스에서 메서드를 만들 때 @staticmethod@classmethod@abstractmethod 등을 붙였는데, 이렇게 @로 시작하는 것들이 데코레이터입니다.

왜 데코레이터를 사용하는가?

간략히 정리하자면 기존의 작업(함수) 앞, 뒤에 추가적인 작업을 손쉽게 사용 가능하도록 도와주는 역할로 사용합니다.

 def 구문을 통해서 메인 구문(함수)을 만들고 난 후에 부가적인 기능을 추가하고 싶을 때가 존재한다? 

이때 데코레이터를 활용하여 자유로운 사용이 가능합니다. 

예를 들어 아래와 같은 메인 구문(함수)가 있다고 가정합니다. 

def main_function():
     print("메인구문 구동합니다.")

print문을 활용해서 문장을 출력하는 간단한 함수입니다. 

만약, 이 함수에 추가적인 문장을 넣고 싶다면?

 

예를 들어 메인 함수을 구동하는데 소요되는 시간을 알고싶은 경우가 있다고 가정합니다. 

간단히 메인 구문에 아래와 같은 함수를 추가하면 될 것입니다. 

import datetime

def main_function():
     a = datetime.datetime.now()
     print("메인 구문 구동합니다.")
     print("구동시간은 {}초 입니다.".format(datetime.datetime.now() - a))

 

하지만 개발을 하다보면 여러 함수 혹은 여러 반복되는 패턴의 함수를 작업해야 할 때가 있습니다. 예를 들어 확인해야하는 작업이 100개가 된다면? 어떻게 작업을 해야할까요? 

# 예시 
def main_function_1():
     print("메인구문 구동합니다. 1번 작업")
     
def main_function_2():
     print("메인구문 구동합니다. 2번 작업")
    
def main_function_3():
     print("메인구문 구동합니다. 3번 작업")
     
.... 

def main_function_100():
     print("메인구문 구동합니다. 100번 작업")

만약 100개의 작업들이 존재한다고 했을때,  아마 다뤄야 할 함수가 이런식으로 구성될 것입니다. 

이 모든 함수의 구동시간을 측정하고 싶다면? 

def main_function_1():
	a = datetime.datetime.now()
	print("메인구문 구동합니다. 1번 작업")
	print("구동시간은 {}초 입니다.".format(datetime.datetime.now() - a))     
     
def main_function_2():
	a = datetime.datetime.now()
	print("메인구문 구동합니다. 2번 작업")
	print("구동시간은 {}초 입니다.".format(datetime.datetime.now() - a))     
    
def main_function_3():
	a = datetime.datetime.now()
	print("메인구문 구동합니다. 3번 작업")
	print("구동시간은 {}초 입니다.".format(datetime.datetime.now() - a))     
     
.... 

def main_function_100():
	a = datetime.datetime.now()
	print("메인구문 구동합니다. 100번 작업")
	print("구동시간은 {}초 입니다.".format(datetime.datetime.now() - a))

반복되는 구문들이 많아지기 때문에 지저분한 작업들이 많아지게 됩니다. 이 뻘짓을 하지 않을 수 있도록 도와주는 것이 데코레이터의 역할입니다. 

 

with Decorator

import datetime 

def calculate_time(func):
	def decorated(): 
		a = datetime.datetime.now()
		func()
		print("구동시간은 {}초 입니다.".format(datetime.datetime.now() - a))     
	return decorated
    
@calculate_time     
def main_function_1():
     print("메인구문 구동합니다. 1번 작업")
     
@calculate_time     
def main_function_2():
     print("메인구문 구동합니다. 2번 작업")
    
@calculate_time    
def main_function_3():
     print("메인구문 구동합니다. 3번 작업")
     
.... 

@calculate_time
def main_function_100():
     print("메인구문 구동합니다. 100번 작업")

decorator 함수를 재사용하면, 간편하게 함수에 전후에 실행하고 싶은 작업들을 실행할 수 있습니다. 단, 기억해야할 점이 있다면 함수의 작업 수행 중간에 끼어드는 작업을 데코레이터로 만들 수는 없다는 것입니다. 단지, 만들어진 함수의 전과 후의 반복적인 작업을 데코레이터로 만든다고 할 수 있습니다. 

함수의 매개변수가 존재할 때 / 반환값을 처리해야 할때. 

def trace(func):          # 호출할 함수를 매개변수로 받음
    def wrapper(a, b):    # 호출할 함수 add(a, b)의 매개변수와 똑같이 지정
        r = func(a, b)    # func에 매개변수 a, b를 넣어서 호출하고 반환값을 변수에 저장
        print('{0}(a={1}, b={2}) -> {3}'.format(func.__name__, a, b, r))  # 매개변수와 반환값 출력
        return r          # func의 반환값을 반환
    return wrapper        # wrapper 함수 반환
 
@trace              # @데코레이터
def add(a, b):      # 매개변수는 두 개
    return a + b    # 매개변수 두 개를 더해서 반환
 
print(add(10, 20))

 

반응형
Comments