Decorator는 말그대로 함수를 꾸며주는 역할을 합니다.
closure코드와 매우 비슷하지만, 함수를 다른 함수의 인자로 전달한다는 점이 다릅니다.

def decorator_function(original_function):  #1
    def wrapper_function():  #5
        return original_function()  #7
    return wrapper_function  #6


def display():  #2
    print 'display 함수가 실행됐습니다.'  #8

decorated_display = decorator_function(display)  #3

decorated_display()  #4

#1 데코레이터 함수인 decorator_function 정의

#2 일반 함수인 display 정의

#3 decorated_display라는 변수에
display 함수를 인자로 decorator_function을 실행한 리턴값을 할당
(리턴값은 original_function == display 라는 것을 기억하는 wrapper_function)
(여기서 wrapper_function 함수는 아직 실행된게 아닙니다.)

#4 decorated_display()를 통해 wrapper_function을 호출

#5 wrapper_function이 호출

#7 original_function인 display 함수가 호출

#8 print 함수가 호출 -> 문자열 출력

복잡하지만 decorator를 사용하면 다음과 같은 코드가 가능해집니다.

def decorator_function(original_function):
    def wrapper_function():
        print '{} 함수가 호출되기전 입니다.'.format(original_function.__name__)
        return original_function()
    return wrapper_function


@decorator_function  #1
def display_1():
    print 'display_1 함수가 실행됐습니다.'


@decorator_function  #2
def display_2():
    print 'display_2 함수가 실행됐습니다.'

display_1()
display_2()
display_1 함수가 호출되기전 입니다.
display_1 함수가 실행됐습니다.

display_2 함수가 호출되기전 입니다.
display_2 함수가 실행됐습니다.

그리고 꾸며야하는 함수가 인자를 받는 다면 wrapper 함수에 가변인자를 받는다고 선언해줘야합니다.

def decorator_function(original_function):
    def wrapper_function(*args, **kwargs):  #1
        print '{} 함수가 호출되기전 입니다.'.format(original_function.__name__)
        return original_function(*args, **kwargs)  #2
    return wrapper_function


@decorator_function
def display():
    print 'display 함수가 실행됐습니다.'


@decorator_function
def display_info(name, age):
    print 'display_info({}, {}) 함수가 실행됐습니다.'.format(name, age)

display()
display_info('John', 25)
display 함수가 호출되기전 입니다.
display 함수가 실행됐습니다.

display_info 함수가 호출되기전 입니다.
display_info(John, 25) 함수가 실행됐습니다.

Decorator는 함수가 아니라 클래스로도 기능을 구현할 수 있습니다.

class DecoratorClass:  #1
    def __init__(self, original_function):
        self.original_function = original_function

    def __call__(self, *args, **kwargs):
        print '{} 함수가 호출되기전 입니다.'.format(self.original_function.__name__)
        return self.original_function(*args, **kwargs)


@DecoratorClass  #2
def display():
    print 'display 함수가 실행됐습니다.'


@DecoratorClass  #3
def display_info(name, age):
    print 'display_info({}, {}) 함수가 실행됐습니다.'.format(name, age)

display()
display_info('John', 25)
display 함수가 호출되기전 입니다.
display 함수가 실행됐습니다.

display_info 함수가 호출되기전 입니다.
display_info(John, 25) 함수가 실행됐습니다.