기존의 함수를 변경시키지 않고 새로운 기능을 추가할 때 데코레이터를 사용합니다.
데코레이터를 사용할 때는 '@' 기호를 이용합니다.


In [ ]:
def print_name(first, last):
    return 'My name is %s, %s' % (last, first)

In [ ]:
def p_decor(func):
    def func_wrapper(*args, **kwargs):
        text = func(*args, **kwargs)
        return '<p>%s</p>' % text
    return func_wrapper

In [ ]:
print_name = p_decor(print_name)

In [ ]:
print_name('jobs', 'steve')

In [ ]:
@p_decor
def print_name2(first, last):
    return 'My name is %s, %s' % (last, first)

In [ ]:
print_name2('jobs', 'steve')

데코레이터에 파라메타를 전달하기 위해 함수를 한번 더 래핑합니다.


In [ ]:
def html_tag(tag):
    def p_decor(func):
        def func_wrapper(*args, **kwargs):
            text = func(*args, **kwargs)
            return '<%s>%s</%s>' % (tag, text, tag)
        return func_wrapper
    return p_decor

In [ ]:
@html_tag('div')
def print_name3(first, last):
    '''div tagging function'''
    return 'My name is %s, %s' % (last, first)

In [ ]:
print_name3('jobs', 'steve')

데코레이터를 사용하면 함수의 원래 이름이 바뀌어 집니다.
functools.wraps 를 사용하여 함수 정보를 바꾸어 줍니다.


In [ ]:
print_name3.__name__

In [ ]:
print_name3.__doc__

In [ ]:
from functools import wraps
def html_tag(tag):
    def p_decor(func):
        @wraps(func)
        def func_wrapper(*args, **kwargs):
            text = func(*args, **kwargs)
            return '<%s>%s</%s>' % (tag, text, tag)
        return func_wrapper
    return p_decor

In [ ]:
@html_tag('div')
def print_name4(first, last):
    '''div tagging function'''
    return 'My name is %s, %s' % (last, first)

In [ ]:
print_name4.__name__

In [ ]:
print_name4.__doc__