데코레이터는 '장식하다'라는 의미에서 나온 개념으로, 함수를 장식하는 도구라 할 수 있다.
데코레이터는 함수를 수정하지 않은 상태에서 추가 기능을 구현할 때 사용한다.
함수를 작성하다보면 메인 구문이 있고, 여기에 부가적인 구문을 추가하고 싶을 때가 있다. 예를 들어 함수의 실행시간을 측정하고 싶다면? 아래와 같이 함수가 시작하는 시간과 함수가 종료되는 시간의 차이를 계산하는 코드를 짤 수 있다.
import time
def myfunc():
start = time.time()
print("함수가 실행됩니다.")
end = time.time()
print("함수 수행시간: %f 초" % (end-start))
myfunc()
이 예제만 놓고 보면, 매우 간단한 함수이기 때문에 이렇게 해도 큰 무리는 없다.
그런데 만약 수행시간을 체크해야 하는 함수가 상당히 많다면 어떨까? 그 함수들 모두에 이런 동일한 기능을 추가하는 것은 꽤 비효율적이라는 것을 알 수 있을 것이다.
그 때 이 반복적이고 부가적인 기능을 데코레이터
로 만들어놓고, 필요할 때마다 불러오면 효율적으로 코드를 짤 수 있다.
데코레이터를 사용하는 경우들
- 로그 남길 때
- 유저의 로그인 상태를 확인할 때
- 프로그램의 성능 테스트 등
데코레이터를 작성해보도록 하자. 우선, 데코레이터의 본질은 클로저이다. 다만 함수를 다른 함수의 인자로 전달한다는 것이 데코레이터의 특별한 점이다.
import time
def decorate(original_func): # 호출할 함수를 매개변수로 받음
def wrapper(): # 호출할 함수를 감싸는 함수
start = time.time()
original_func() # 매개변수로 받은 함수를 호출
end = time.time()
print("함수 수행시간: %f 초" % (end - start))
return wrapper # wrapper 함수 반환
def myfunc():
print("함수가 실행됩니다.")
decorated_myfunc = decorate(myfunc) # 데코레이터에 호출할 함수를 넣음
decorated_myfunc() # 반환된 함수를 호출
@을 사용하여 좀 더 간편하게 데코레이터를 사용할 수 있다. myfunc함수 바로 위에 @데코레이터 함수명
이라는 어노테이션을 추가하였다. 파이썬은 함수명 위에 있는 어노테이션은 데코레이터 함수로 인식한다. 따라서 myfunc함수는 decorate함수를 거쳐서 수행될 것이다.
import time
def decorate(original_func):
def wrapper():
start = time.time()
original_func()
end = time.time()
print("함수 수행시간: %f 초" % (end - start))
return wrapper
@decorate # @데코레이터
def myfunc():
print("함수가 실행됩니다.")
myfunc() # 함수를 그대로 호출
참고사이트
https://www.hanbit.co.kr/media/channel/view.html?cms_code=CMS5689111564
https://dojang.io/mod/page/view.php?id=2427
https://bluese05.tistory.com/30
https://leo-bb.tistory.com/49
https://wikidocs.net/83687
http://schoolofweb.net/blog/posts/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EB%8D%B0%EC%BD%94%EB%A0%88%EC%9D%B4%ED%84%B0-decorator/