데코레이터?
파이썬에서 데코레이터란, 일반적으로 함수의 앞뒤에 미리 정의해둔 처리를 추가적으로 수행할 수 있게끔 치장하는 역할을 수행하는 컴포넌트이다. 아래와 같은 logger 함수를 데코레이터로 선언한다고 하면,
def logger(function):
def wrapper(*args, **kwargs):
"""wrapper documentation"""
print(f"----- {function.__name__}: start -----")
output = function(*args, **kwargs)
print(f"----- {function.__name__}: end -----")
return output
return wrapper
위의 logger가 하는 일은 3,5 번째 줄에서 볼 수 있듯이 주어진 함수의 시작 및 끝을 print로 알려주는 것이다. 이걸 직접 써보면 아래와 같이 써볼 수 있다.
logger 함수는 한번 정의해두면 그 다음부터는 두가지 방식으로 사용이 가능한데, 아래의 코드블럭처럼 say_hello라는 함수가 있다고 했을 때,
def say_hello():
"""hello documentation"""
print('hello')
time.sleep(1)
일반적인 wrapper function으로 사용해서
first_hello = logger(say_hello)
first_hello()
와 같이 사용하거나 아니면,
@logger
def say_hello():
"""hello documentation"""
print('hello')
time.sleep(1)
say_hello()
와 같이 사용할 수 있다. 첫번째와 같이 사용하는 경우 함수 이름을 정확하게 override 해주지 않으면 본 예시에서의 logger같이 함수명을 사용하는 wrapper가 적절하게 사용되기 어려운 단점이 생긴다.
@wraps
위의 예시에서 보면, logger 데코레이터는 내부에서 새로 정의하는 wrapper 함수 객체를 선언하고 이를 반환한다. 그렇기 때문에, 데코레이터를 통해서 한번 묶인 함수는 본래 자신의 name이나 document, 그리고 help 호출 시 나오는 변수 리스트 정보를 잃고 만다.
관련 기타 블로그들을 보았을 때, 디버깅에도 어려움이 생긴다고 하는데, 직접 해봤을때는 wrapper call이 traceback에 추가되는거 말고는 딱히 잘 모르긴 하겠지만 일단 docstring을 잃게 된다는 거 자체로 프로젝트에서 autodoc(sphinx, readthedocs등) 모듈을 사용시 매우 곤란한 문제임은 맞다.
이를 피할 수 있도록 해주는 빌트인 데코레이터가 바로 @wraps 이다. @wraps 데코레이터는 데코레이터 함수 정의 시 그 내부에 사용하면 되는데, 그러면 타겟함수의 이름이나 docstring을 wrapper에게 그대로 상속시켜준다. 아래와 같이 사용하면 원했던 대로 함수 이름 및 도큐먼트가 잘 상속되는걸 확인할 수 있다.
import time
from functools import wraps
def logger(function):
@wraps(function)
def wrapper(*args, **kwargs):
"""wrapper documentation"""
print(f"----- {function.__name__}: start -----")
output = function(*args, **kwargs)
print(f"----- {function.__name__}: end -----")
return output
return wrapper
@logger
def say_hello():
"""hello documentation"""
print('hello')
time.sleep(1)
참고원문:
https://towardsdatascience.com/12-python-decorators-to-take-your-code-to-the-next-level-a910a1ab3e99
12 Python Decorators To Take Your Code To The Next Level
Do more things with less code without compromising on quality
towardsdatascience.com
https://cjh5414.github.io/wraps-with-decorator/
Python decorator에 @wraps를 사용해야 하는 이유
Jihun's Development Blog
cjh5414.github.io
https://stackoverflow.com/questions/308999/what-does-functools-wraps-do
What does functools.wraps do?
In a comment on this answer to another question, someone said that they weren't sure what functools.wraps was doing. So, I'm asking this question so that there will be a record of it on StackOverfl...
stackoverflow.com
'잡지식 저장고 > Python' 카테고리의 다른 글
[아나콘다] 기존 환경에 environment.yml로 패키지 추가 설치하기 (0) | 2023.08.26 |
---|---|
데코레이터란 : Python Decorator 예시집 - 2 (1) | 2023.03.05 |
Python Multiprocessing으로 병렬처리, 비디오 처리로 맛보기 (1) | 2023.02.20 |
Python setup.py 에서 닌자 관련 에러 날 때 (0) | 2021.04.13 |
파이썬에서 로그 한 줄에 계속 프린팅하기 (0) | 2021.04.12 |
댓글