파이썬에 ‘@’키워드가 뭔지 궁금했다. 알고보니 데코레이터라는 거라고 한다.
데코레이터란?
@classmethod, @staticmethod, @property과 같이 ‘@’키워드가 붙은 건 전부 파이썬의 데코레이터이다.
또, 데코레이터는 함수를 장식할 수 있다는 특징이 있다.
데코레이터는 fastapi로 서버를 만들때나 discord봇을 만들 때 사용하는 걸 봤다. getter, setter를 구현할때도 쓰인다. 앞으로 많이 사용할 것 같으니 그 원리를 정확하게 이해하고 가자!
이 데코레이터라는 것을 한번 만들어보자.
def log(func):
def wrapper(*args, **kwargs):
print(f'start {func.__name__} function')
func(*args, **kwargs) # 진짜 함수 실행
print(f'end {func.__name__} function')
return wrapper # 장식할😊 함수를 반환
@log
def printHello():
print("Hello")
printHello()
위 코드는 함수 위에 @log만 붙이면 아래와 같은 로그를 다 띄워준다.
start printHello function
Hello
end printHello function
wow데코레이터를 하나 더 만들어봤다. 데코레이터는 여러개 장착할 수 있다. 이때 실행 순서는 위에서 아래로 실행이 된다.
def wow(func):
def wrapper(*args, **kwargs):
print('wow')
func(*args, **kwargs)
return wrapper
@log
@wow
def printHello():
print("Hello")
실행 결과는 아래와 같다. start어쩌구가 먼저 실행이 된 후 wow가 출력된 것을 볼 수 있다.
start wrapper function
wow
Hello
end wrapper function
함수 호출을 제한하는 데코레이터도 만들 수 있다.
def limit_calls_decorator(max_calls):
def decorator(func):
calls = 0
def wrapper(*args, **kwargs):
nonlocal calls
if calls < max_calls:
calls += 1
return func(*args, **kwargs)
else:
raise Exception("함수 호출 횟수 초과")
return wrapper
return decorator
아래 실행 결과를 보면 3번째 실행할 때까지는 문제가 없었지만 그 이후는 예외가 발생한다.
예제 함수 실행
예제 함수 실행
예제 함수 실행
함수 호출 횟수 초과
함수 호출 횟수 초과
Traceback (most recent call last):
.. 어쩌구 저쩌구 에러~
클래스 안에서도 데코레이터를 사용할 수 있다.
class TestExample:
def _decorator(func):
def wrap(self, *args, **kargs):
print("Start", func.__name__)
func(self, *args, **kargs)
print("End", func.__name__)
return wrap
@_decorator
def test(self, a, b, c):
print("Variables :", a, b, c)
t = TestExample()
t.test("1", 2, c="345")
클래스를 사용해서도 데코레이터를 만들 수 있다.
아래는 함수가 호출될 때마다 count변수를 증가시킨다. 함수의 호출 횟수를 알 수 있다는 말이다.
class emoticon:
def __init__(self, emoticon):
self.count = 0 # 호출 회수 저장 필드
self.emoticon = emoticon
def __call__(self, func):
def inner(*args, **kwargs):
self.count += 1
inner.count = self.count # 함수 객체에서 바로 사용 할 수 있도록
print(self.emoticon, ' ', end='')
return func(*args, **kwargs)
return inner
@emoticon('-_-')
def say_hi(name):
print(f'hi {name}!')
say_hi('Jason')
print(say_hi.count)
데코레이터의 장점과 활용
데코레이터를 사용하면 중복되는 코드를 줄여 코드 가독성을 높이고 유지보수성을 높일 수 있다.
관심사의 분리도 할 수 있다. 함수는 함수의 핵심 기능에만 집중하고 나머지 부가기능은 데코레이터에게 맞기는 것이다.
데코레이터로 만들 수 있는 것은 무궁무진하다! 함수의 실행 시간을 측정하는 타이머나 로깅, REST API구축 등등…
데코레이터 주의사항
데코레이터 사용 시 함수의 메타데이터가 변경될 수 있다. 또, 여러 데코레이터를 사용할 때 실행 순서 또한 주의해야 한다.
'공부 > Python' 카테고리의 다른 글
Python - for-else과 while-else문을 알아보자 (0) | 2024.06.18 |
---|---|
Python - 멤버 변수를 출력하는 다양한 방법 (0) | 2024.06.17 |
Python - 복소수 사용하는 방법 (0) | 2024.06.08 |