파이썬의 데코레이터란?
먼저 Decorate는 '장식하다' 라는 의미가 있고, 따라서 직역하면 '장식자'라는 의미가 된다. (구글 번역기에서는 a person who decorates something. 로 정의되어 있다.)
파이썬에서도 원래 뜻과 비슷한 의미로 사용되는데 @ 기호로 표현 할 수 있으며, 클래스나 메소드를 정의할 때 많이 사용되어 진다.
데코레이터는 직접 정의하여 사용하거나 미리 정의된 내용을 가져와 사용이 가능하다.
(정의된 데코레이터는 @property, @classmethod, @staticmethod 등이 있다.)
데코레이터를 작성하면 원본 메소드의 내용을 수정하지 않고 여러 기능을 추가할 수 있게 된다.
- 메소드(함수)의 실행시간 측정
- 실행과 종료에 로그 기능 추가
- ...
메소드 데코레이터 정의하기
데코레이터는 크게 클래스 데코레이터와 메소드 데코레이터로 나눠진다.
메소드 데코레이터는 메소드를 장식하기 위한 데코레이터로 기본적인 형태는 아래 코드를 따르게 되며,
def decorator_1(func):
def wrapped_func():
func()
return wrapped_func()
만들어진 데코레이터의 사용은 아래 코드와 같다.
# 메소드 데코레이터 정의
def decorator_1(func):
def wrapped_func():
print("start")
func()
print("end")
return wrapped_func
# 사용
@ decorator_1
def test_func():
print("logic")
test_func()
위 사진은 데코레이터를 사용한 결과인데 내용을 보면 가장 마지막 줄에 test_func()을 호출했지만 decorator_1에 내부에 정의된 wrapped_func의 기능이 수행된 것을 볼 수있다.
하지만 데코레이터를 사용하는 함수의 매개변수를 바꾸고 실행하면 TypeError가 발생한다.
정상적으로 메소드에 인수를 받아 사용하려면 데코레이터의 수정이 조금 필요하다.
아래 코드를 보면 wrapped_func에 *args가 매개변수로 추가되었다.
*을 사용하여 non-keworded arguments 형식으로 인수를 받을 수 있는데 이렇게 사용하면, 키워드가 없는 가변 인수가 되어 여러개의 인수를 받는 것이 가능해진다. (만약 메소드에 키워드가 필요하다면 **(keworded arguments)를 사용)
def decorator_1(func):
def wrapped_func(*args):
print("start - ", func.__name__)
func(*args)
print("end - ", func.__name__)
return wrapped_func
@ decorator_1
def test_func(str_var, int_tmp, a, b, c):
print(str_var, int_tmp, a, b, c)
test_func("test", 12, 1, 2, 3,)
위 코드에서 매개변수를 받아 출력을 했지만, test_func 함수의 결과 값은 받아볼 수 없다.
wrapped_func 내부에서 func의 결과 값을 받아 return 해줬다.
def decorator_1(func):
def wrapped_func(*args):
print("start - ", func.__name__)
ret= func(*args)
print("end - ", func.__name__)
return ret
return wrapped_func
@ decorator_1
def test_func(str_var, int_tmp, a, b, c):
print(str_var, int_tmp, a, b, c)
return a + b
print(test_func("test", 12, 1, 2, 3,))
클래스 데코레이터
위에서 작성한 데코레이터를 클래스 내에 넣어 작성해보았다.
메소드 데코레이터와 동일한 기능을 수행하는 것을 볼 수 있다.
class myClass:
def myClass_LoggingDecorator(func):
def wrapped_func(*args):
print("start - ", func.__name__)
func(*args)
print("end - ", func.__name__)
return wrapped_func
@ myClass_LoggingDecorator
def test_func(str_var, int_tmp, a, b, c):
print(str_var, int_tmp, a, b, c)
myClass.test_func("test", 12, 1, 2, 3,)
클래스 데코레이터 - 활용
import time
import datetime
class myClass:
def myClass_RunningtimeDecorator(func):
def wrap(*args):
start_r = time.perf_counter()
start_p = time.process_time()
ret = func(*args)
end_r = time.perf_counter()
end_p = time.process_time()
elapsed_r = end_r - start_r
elapsed_p = end_p - start_p
print(f'{func.__name__} : {elapsed_r:.6f}sec (Perf_Counter) / {elapsed_p:.6f}sec (Process Time)')
return ret
return wrap
def myClass_LoggingDecorator(func):
def wrapped_func(*args):
file_name = f"log_{datetime.datetime.today().strftime('%Y-%m-%d')}.txt"
File = open(file_name, "w")
File.write(f"start - {func.__name__}, DateTime : {datetime.datetime.now()}\n")
ret = func(*args)
File.write(f"end - {func.__name__}, DateTime : {datetime.datetime.now()}\n")
File.close()
return ret
return wrapped_func
#@ myClass_RunningtimeDecorator
@ myClass_LoggingDecorator
def test_sum(str_var, a, b):
print(str_var, a + b)
return a + b
print ("res2 :", myClass.test_sum("res1 :", 1, 2))
'프로그래밍 > Python' 카테고리의 다른 글
[python] JWT 모듈 (0) | 2022.09.13 |
---|---|
[Python] Yahoo_fin 모듈 (0) | 2022.09.11 |
[Python] Paramiko 모듈 (0) | 2022.07.07 |
[Python] min, max 함수 (0) | 2022.03.10 |
[python] lambda 표현식 (0) | 2022.01.07 |
[python] 실행 시 필요한 패키지 자동 설치 (0) | 2022.01.01 |
댓글