안녕하세요!
python decorator(데코레이터) 간단 정리 본문
데코레이터(Decorator)
- 함수의 재사용성을 확장한 개념 방법
데코레이터의 개념을 이해하기위해선, 파이썬에서의 first class 함수, closure함수를 알아야한다.
* first class function : 함수 자체를 argument로 다른 함수에 전달 또는 다른 함수의 결과값으로 return 할 수도 있고, 함수를 변수에 할당, 데이터 구조안에 저장할 수 있는 함수를 뜻한다.
함수 실행시간을 확인하는 데코레이터 프로그램을 한번 만들어보도록 하자.
우선 시간을 확인하려면 time을 import 해야한다.
import time
def timer_decorator(func) :
def wrapper(*args, **kwargs) :
start_time = time.time()
rs = func(*args, **kwargs)
end_time = time.time()
return rs
return wrapper
@timer_decorator
def exe_function() :
print("실제 처리할 함수")
time.sleep(2)
# 2초 대기 : 데코레이터가 처리되는 시간을 잠시 주기 위함.
클로져 함수와 많이 닮아있다. 함수 내부의 함수가 있지만 @timer_decorator에 있는 exe_function()이 데코레이터의func자리에 들어가서 작동하기 때문에, 실제적으로는 내부함수가 작동한다.
exe_function()
start_time = 1699930636.5838223
실제 처리할 함수
end_time = 1699930638.5855138
해당하는 함수에서는 중간에 rs 라는 값이 function을 한번 실행시켰기 때문에, 실제 처리할 함수 라는게 같이 프린트되어 등장했다. start와 end time은 unix time으로 변환되어 표시됐다. 거의 2초간격으로 나온것을 볼 수 있다.
(한국시간으로는 Tue Nov 14 2023 11:57:18 이다)
데코레이터 함수를 배울 때 이해가 잘 되지 않았다.
간단히 생각하면 저기로 들어간다 하고 마는건데, 왜 들어가는건지 어떻게 들어가는건지가 궁금했다.
메모리의 주소값이 기존에 timer_decorator이 가리키는자리와, wrapper가 가리키는 주소와 exe_function이 가리키는 주소는 각각 다르지만, 함수가 실행되면서 decorator인 exe_function이 func 자리에 들어가면서 wrapper 와 같은 메모리 주소를 갖게 되고, 같은 메모리 주소를 가졌기 때문에 exe_function을 실행 했을때, 내부함수가 작동하는 방식이다.
추가로 데코레이 내부함에서 처리된 결과를 받아보는 함수를 보도록 하자.
def check_permission(param_id) :
def decorator(func) :
def wrapper(*args, **kwargs) :
check_id = "admin"
if check_id == param_id :
args = ["인증성공"]
return func(*args, **kwargs)
else :
## raise = 강제로오류발생 permissionError 를 발생시키겠습니다
raise permissionError("접근 불가!!")
return wrapper
return decorator
@check_permission(param_id = "admin")
def admin_function(rs_msg) :
admin_function()
인증결과 : 인증성공
복잡해보이지만, 결국은 데코레이터가 func로 들어가며 최상위함수기준으로 내부의 내부함수를 작동시키는 주소를 가지고, 파라미터를 전달해서 인증성공으로 결과가 리턴되는것을 볼 수 있다.
2개의 대문자를 넣었을때, 2개의 소문자로 변환되어 나오는 데코레이터를 만들어보도록 하자.
def decorator_upper(func) :
def wrapper(*args, **kwargs) :
args = [arg.lower() for arg in args]
return func(*args, **kwargs)
return wrapper
@decorator_upper
def getUpper(param1, param2) :
getUpper("A","B")
변환결과 : a / b
데코레이터 함수를 사용하는 이유는, 기존의 함수가 계속해서 메모리에 올라가있는 방식으로 작동하므로, 내부함수를 이용하여 결과값만 얻어내고 함수자체는 메모리에서 없애버리는 역할을하여 최적화가 되고, 함수를 숨겨주는 역할을 할 수 있기 때문이다.
이 점을 인지하고 사용하기 바란다!
'개발일지 > python' 카테고리의 다른 글
python Iterator(이터레이터)정리2 짝수반환, 텍스트 추출 (0) | 2023.11.16 |
---|---|
python Iterator(이터레이터)정리1 메모리 사용량 확인 (0) | 2023.11.16 |
python closure(클로저)를 알아보자 (2) | 2023.11.14 |
python 클래스를 이용한 도서 키오스크 만들기. (2) | 2023.11.13 |
예외처리 (2) | 2023.11.12 |