질문이 있으십니까?

기본 컨텐츠 및 사용자가 직접 참여하여 만들어진 다양한 내용을 검색합니다.

Python @ (decorator)

뭔가?

  • 데코레이터 꾸며주다
  • 한마디로 대상 함수를 wrapping하고, 이 wrapping된 함수의 앞뒤에 추가적으로 꾸며질 구문들을 정의해서 손쉽게 재사용 가능하게 해주는 것

왜 쓰나?

# 만약, 이런코드가 기존에 존재했다고 칩시다.
import datetime

def main_function():
  print(datetime.datetime.now())
  print("Main Function Start")
  print(datetime.datetime.now())

def main_function_1():
  print('Main Function 1 Start')

def main_function_2():
  print('Main Function 2 Start')

def main_function_3():
  print('Main Function 3 Start')

...
100번 반복된 소스코드 (이미 구현되어 가동되고 있는 소스라고 가정)
# 위의 반복되는 소스코드에 앞뒤로 날짜를 찍어주는 기능을 구현한다고 가정합시다.
import datetime

def main_function_1():
  print datetime.datetime.now()
  print "MAIN FUNCTION 1 START"
  print datetime.datetime.now()

def main_function_2():
  print datetime.datetime.now()
  print "MAIN FUNCTION 2 START"
  print datetime.datetime.now()

def main_function_3():
  print datetime.datetime.now()
  print "MAIN FUNCTION 3 START"
  print datetime.datetime.now()

이런 코드를 100번 넣어야겠지요.
반복되는 구문이 많아지다 보니 점점 소스가 지저분해지고 가독성도 떨어집니다.

함수(def)를 통한 활용

import datetime

def datetime_decorator(func):
  def decorated():
    print datetime.datetime.now()
    func()
    print datetime.datetime.now()
  return decorated

@datetime_decorator
def main_function_1():
  print "MAIN FUNCTION 1 START"

@datetime_decorator
def main_function_2():
  print "MAIN FUNCTION 2 START"

@datetime_decorator
def main_function_3():
  print "MAIN FUNCTION 3 START"

100번 반복
decorator 함수를 재사용 함으로써, main 함수에 대한 가독성과 직관성이 훨씬 좋아진 것을 볼 수 있다. 그리고 같은 패턴을 여러번 사용하더라고 간단히 @를 붙이면 끝이므로 사용도 간편하다.
  • 원리1 먼저 decorator 역할을 하는 함수를 정의하고, 이 함수에서 decorator가 적용될 함수를 인자로 받는다. python 은 함수의 인자로 다른 함수를 받을 수 있다는 특징을 이용하는 것이다.
  • 원리2 decorator 역할을 하는 함수 내부에 또 한번 함수를 선언(nested function)하여 여기에 추가적인 작업(시간 출력) 을 선언해 주는 것이다.
  • 원리3 nested 함수를 return 해주면 된다.

클래스(class)를 통한 활용

import datetime

class DatetimeDecorator:
    def __init__(self,f):
        self.func = f

    def __call__(self,*args,**kwargs):
        print(datetime.datetime.now())
        self.func(*args,*kwargs)
        print(datetime.datetime.now())

class MainClass:
    @DatetimeDecorator
    def main_function_1():
        print("Main Function 1 Start")

    @DatetimeDecorator
    def main_function_2(*args,**kwargs):
        print("Main Function 2 Start")

    @DatetimeDecorator
    def main_function_3():
        print("Main Function 3 Start")
        
my = MainClass()
my.main_function_1()
my.main_function_2('a',b='1')

댓글을 작성하세요

문서 이력

  • 2020-06-13 날짜로 신달수 님으로 부터 컨텐츠명이 변경 되었습니다.
  • 2020-07-29 날짜로 신달수 님께서 수정 작업을 하였습니다.