youngfromnowhere
[Python] Decorator 본문
Python flask를 배우다보니 반가운 구문을 만나게 되었다.
바로 '@'을 쓰는 python decorator다.
예전에 python의 property 기능에 대해 파다가 만난 개념이다. 오늘 여기에 다시정리해본다.
https://docs.python.org/3/glossary.html#term-decorator
Glossary — Python 3.11.0 documentation
An extension of the familiar real number system in which all numbers are expressed as a sum of a real part and an imaginary part. Imaginary numbers are real multiples of the imaginary unit (the square root of -1), often written i in mathematics or j in eng
docs.python.org
다음과 같이 function deco가 정의되어 있다고 하자.
#code block 01
def deco(arg):
... body ...
return some_obj
이 때 다음 두 code는 서로 equivalent 하다.
#code block 02
@deco
def main(arg):
... body ...
return some_obj
#code block 03
def main(arg):
... body ...
return some_obj
main = deco(main)
위에 정의된 deco에 function object를 입력하면 deco는 function object를 return한다. 이것을 반복적으로 함수들의 정의를 조작하는데 쓸 수 있다. 다만 대상 함수의 body 중간에 code를 끼워놓을 수는 없다. 대상 함수의 body 앞 뒤에 code를 추가하기 쉽도록 만든 기능이기에 decorator라 칭하는 것이다.
예시.
#code block 04
def deco(funcobj):
def wrapper(arg):
print("this string is added by decorator")
funcobj(arg)
print("this string is added by decorator")
return wrapper
@deco
def main(arg):
print(f"main(arg={arg}) has been called")
if __name__ == '__main__':
main(3)
main(4)
main(5)
code block 04의 실행결과는 다음과 같다.
this string is added by decorator
main(arg=3) has been called
this string is added by decorator
this string is added by decorator
main(arg=4) has been called
this string is added by decorator
this string is added by decorator
main(arg=5) has been called
this string is added by decorator
다음과 같이 class 형식으로 decorator를 정의할 수도 있다.
#code block 05
class DecoClass:
def __init__(self, funcobj):
self.f = funcobj
def __call__(self, arg):
print(f"{self.f.__name__} is decorated by DecoClass")
self.f(arg)
print(f"{self.f.__name__} is decorated by DecoClass")
@DecoClass
def main(arg):
print(f"main(arg={arg}) has been called")
if __name__ == '__main__' :
main(1)
main(3)
main(7)
@DecoClass 밑에 main이 정의된 것은 main = DecoClass(main) 과 같은 코드이므로
__init__의 funcobj 인자로 main이 전달되어 DecoClass의 instance가 생성되고 여기에 main이라는 이름이 다시 assign 된다.
이후 main(3)과 같이 호출하면 이는 main.__call__(3)과 equivalent 하므로 __call__의 body가 실행된다. code block 05의 실행결과는 다음과 같다.
main is decorated by DecoClass
main(arg=1) has been called
main is decorated by DecoClass
main is decorated by DecoClass
main(arg=3) has been called
main is decorated by DecoClass
main is decorated by DecoClass
main(arg=7) has been called
main is decorated by DecoClass
main(1), main(3), main(7)의 실행 전후에 DecoClass에 의한 동작이 실행됨을 알 수 있다.
'Python' 카테고리의 다른 글
| [Python] python의 special methods (0) | 2022.11.17 |
|---|---|
| [Python] Decorator3. Property (0) | 2022.11.16 |
| [Python] Decorator 2. abstractmethod() (0) | 2022.11.15 |
| [Python] 가상환경 (0) | 2022.11.03 |
| [Python] Python의 Method Call (0) | 2022.10.31 |