Decorator
decorator는 함수를 파라미터로 받아서 그 함수를 실행하면서 다른 기능들을 실행할 수 있도록 해주는 패턴이다. 여기서 다른 기능들이란 인자로 받는 함수의 실행 전, 후로 로그인, try-catch문 등 반복적으로 수행되는 작업을 의미한다.
참조1의 예시가 가장 이해하기 좋고 일반적인 예제인것 같다. decorator_exam 메서드에서 인자로 받아오는 함수 func를 내부 함수 decorator_func에서 다른 기능들과 함께 실행한 후 리턴하도록 만들어준다. 그러면 @decorator_exam을 위에 써준 함수들을 실행했을 때, 해당 기능이 작동한다.
def decorator_exam(func):
def decorator_func():
print('함수 시작')
func()
print('함수 끝')
return decorator_func()
@decorator_exam
def hi_function():
print('hi')
## '함수 시작'
## 'hi'
## '함수 끝'
@decorator_exam
def hello_function():
print('hello')
## '함수 시작'
## 'hello'
## '함수 끝'
클래스 형태로 만들 수도 있다고 한다. init 메서드에서 멤버변수로 함수인 func를 받아오고, call 메서드에 함수와 함께 실행할 다른 기능들을 작성해준다.
class DecoratorExam:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('함수 시작')
self.func(*args, **kwargs)
print('함수 끝')
@Wraps
참조 1의 조금 더 실질적인 예제 코드이다. login_test_user 메서드에서 파이썬 크롤링 코드에서 사용되는 코드를 작성했다. 로그인 버튼을 누르고, id, pw를 입력한다. 그리고 login_test_user_with_browser 메서드는 Decorator를 정의한다. 상기 login_test_user 메서드를 실행한 후 인자로 받아온 method를 실행한다.
from functools import wraps
def login_test_user(self):
if hasattr(self, 'browser'):
self.browser.get(self.live_server_url)
self.browser.find_element_by_id('login_button').click()
self.browser.find_element_by_id('id_username').send_keys(self.test_user.username)
self.browser.find_element_by_id('id_password').send_keys('kboard123')
self.browser.find_element_by_class_name('btn-primary').click()
def login_test_user_with_browser(method):
@wraps(method)
def _impl(self, *args, **kwargs):
login_test_user(self)
method(self, *args, **kwargs)
return _impl
여기서 @wraps(method)는 실제 실행 시 @decorator가 실행한 메서드의 이름으로 실행되도록 한다. @wraps가 없으면 아래 실행 코드에서 @login_test_user_with_browser 데코레이터에 의해서 디버깅 시에 '_impl' 이라는 이름의 메서드가 실행된다. 이러면 어떤 메서드에 데코레이터를 적용하더라도 '_impl'이라는 메서드가 실행되는 것으로 보인다. @wraps를 적용하면 인자로 받아온 함수인 test_delete_post 메서드가 실행되는 것으로 보여진다.
class DeletePostTest(FunctionalTest):
@login_test_user_with_browser
def test_delete_post(self):
...
참조
1. decorator 개념 및 적용, @wraps 예제
https://cjh5414.github.io/python-decorator/
'Programming-[Backend] > Python' 카테고리의 다른 글
파이썬 itertools.groupby 주의사항. 키가 연속으로 붙어있어야함 (0) | 2024.02.22 |
---|---|
[TIL] Python O(n)은 몇 초 정도일까 (Casting, converting) (1) | 2023.09.18 |
[탐험] 테스트하기 좋은 코드, private과 given이 너무 많을 때 (0) | 2023.09.18 |
[TIL] 파이썬 단일 메서드 실행 디버깅 - shell_plus (0) | 2023.09.14 |
[TIL] PyPy, CPython과 session close(), reference counting (0) | 2023.09.13 |