일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- list
- Google Spreadsheet
- Java
- Excel
- gas
- Apache
- Mac
- GIT
- math
- Tkinter
- c#
- SQL
- 파이썬
- hive
- django
- Redshift
- PySpark
- Github
- PostgreSQL
- google apps script
- numpy
- Kotlin
- Python
- array
- dataframe
- PANDAS
- matplotlib
- string
- Google Excel
- Today
- Total
달나라 노트
Python Basic : decorator (@) 본문
Python의 decorator라는 것에 대해 알아보겠습니다.
Python을 하다보면 아래처럼 @로 시작하는 부분을 볼 수 있습니다.
@test_function
def sub_func():
print('This is test message.')
이렇게 @(At sign)을 이용하는 것을 decorator라고 합니다.
decorator가 뭔지를 먼저 간단하게 말하자면 '기존 함수에 decorator 함수를 추가해서 기존 함수를 장식(decorate)해주는 기능'이라고 할 수 있습니다.
지금은 이게 무슨 말인지 몰라도 됩니다.
한번 예시를 보시죠.
def main():
print('main function started')
main()
-- Result
main function started
위 코드를 실행하면 main함수가 실행되면서 main function started라는 구문이 출력됩니다.
아주 간단한 함수죠.
근데 어떠한 상황에 의해 main function을 약간 수정할 필요가 생겼습니다.
def main():
print('user_1130 login')
print('main function started')
print('user_1130 logout')
main()
-- Result
user_1130 login
main function started
user_1130 logout
그래서 위처럼 수정하였습니다.
main function started라는 구문 앞 뒤에 user_1130이 로그인했다, 로그아웃했다라는 print 구문을 추가했습니다.
보통 이렇게 어떤 함수에 추가적인 기능이 필요한 경우 해당 함수 자체를 수정하게되죠.
위 경우는 main 함수 1개만 수정하면 됩니다.
근데 만약에 main함수, main_1 함수, main_2 함수, ... 등 코드를 작성하며 만든 수많은 함수들의 내용에 해당 함수가 시작될때 user의 login 메세지를 출력하고 해당 함수의 끝부분에 user의 logout 메세지를 추가해야한다면 어떻게 해야할까요?
예를들어 위처럼 고쳐야 할 함수가 100개가 있다면 그 100개의 함수 각각에 user_1130 login / user_1130 logout 메세지를 출력해주는 print 구문을 일일이 다 적어야 할 것입니다.
상당히 불편한 일이 아닐 수 없죠.
이때 사용할 수 있는 Python의 특징이 있습니다.
바로 어떤 함수가 parameter로서 다른 함수를 받을 수 있다는 것이지요.
def decorator(func):
def decorated():
print('user_1130 login')
func()
print('user_1130 logout')
return decorated
def main():
print('main function started')
main = decorator(main)
main()
-- Result
user_1130 login
main function started
user_1130 logout
위 코드를 봅시다.
main function은 main function started라는 구문만 print하도록 되어있습니다.
한 가지 차이는 바로 decorator 함수가 생겼다는 것이죠.
decorator 함수를 봅시다.
decorator 함수 내부에서는 decorated란 함수를 생성하고 생성된 decorated 함수를 return해주죠.
그리고 decorated 함수는 decorator 함수가 parameter로서 받은 함수(func) 앞 뒤에 user_1130 login, user_1130 logout이라는 메세지 print 구문을 추가해줍니다.
그래서 main = decorator(main) 이 부분을 보면
main function started라는 메세지만을 출력해주던 main 함수를
decorator 함수에 넣어서 user_1130 login / user_1130 logout이라는 추가 print문을 가지도록 장식(decorate) 해준 후 이것을 main 변수에 재할당하여 새로운 main 함수를 만들어주고있습니다.
그래서 만들어진 main 함수를 실행시키면 우리가 원하던대로 login, logout 메세지까지 잘 뜨게되죠.
자, 이 얘기를 왜 하냐구요?
이제 저희가 처음에 얘기했던 @(At sign)을 사용할 때가 왔습니다.
바로 위에서 다뤘던 코드를 아래처럼 바꿔보겠습니다.
기능과 코드가 실행되는 과정은 거의 100% 동일하다고 보시면 됩니다.
def decorator(func):
def decorated():
print('user_1130 login')
func()
print('user_1130 logout')
return decorated
@decorator
def main():
print('main function started')
main()
-- Result
user_1130 login
main function started
user_1130 logout
결과를 보면 완전히 똑같죠?
결과만 같은 것이 아니라 코드가 의미하는 바도 완전히동일합니다.
위에서 본 2가지 동일한 예시의 중요한 부분을 비교해봅시다.
def main():
print('main function started')
main = decorator(main)
@decorator
def main():
print('main function started')
위 2가지 부분은 동일합니다.
즉, 우리가 Python 코드에서 @(At sign)으로 시작하여 그 뒤에 함수를 적는다는 것의 의미는
@ 에 적힌 함수(decorator)의 parameter로 @ 다음에 정의되는 함수(main)를 전달하여
decorator 함수의 기능이 추가된 main함수로 장식(decorate)하라는 뜻입니다.
이렇게 어떤 함수의 기능에다가 decorator의 기능을 추가하여 장식해준다는 것을 보면
앞에서 말했던 다음의 내용을 이제 이해하실 수 있을겁니다.
"decorator가 뭔지를 먼저 간단하게 말하자면 '기존 함수에 decorator 함수를 추가해서 기존 함수를 장식(decorate)해주는 기능'이라고 할 수 있습니다."
처음 보면 복잡할 수 있지만 위 내용을 곰곰이 되짚어보면 금방 이해가 되실 겁니다.
이렇게 Python 함수들에 대해 decorator가 무엇을 의미하며 어떻게 사용할 수 있는지를 알아봤습니다.
엄청 자주 사용되는 내용은 아니지만 decorator는 class에서도 사용할 수 있습니다.
위 내용을 이해하셨다면 아래 코드도 이해하실 수 있을겁니다.
class Decorator:
def __init__(self, f):
self.func = f
def __call__(self, *args, **kwargs):
print('user_1130 login')
self.func(self)
print('user_1130 login')
class MainClass:
@Decorator
def main(self):
print('main function started')
@Decorator
def sub_test(self):
print('sub_test function started')
cls_main = MainClass()
cls_main.main()
print('')
cls_main.sub_test()
-- Result
user_1130 login
main function started
user_1130 login
user_1130 login
sub_test function started
user_1130 login
class의 decorator가 function에서 사용했던 decorator와 다른 점은
Decorator class에서 __call__의 형태로 decorator function을 설정해줘야 한다는 것입니다.
또한 Decorator class의 __init__ 함수의 parameter 중 f가 의미하는 것은 외부에서 받을 함수(main, sub_test 등)를 의미한다고 볼 수 있습니다.