본문 바로가기
코딩 연습/코딩배우기

[python] 파이썬 데코레이터 (Decorator)

by good4me 2020. 9. 16.

goodthings4me.tistory.com

 

■ 파이썬 데코레이터 (Decorator)는 꾸며주는(덧붙여주는) 역할을 하는 함수 또는 클래스로써 클러저와의 차이점은 함수를 다른 함수의 인자로 전달한다는 점이다. 즉, 데코레이터 함수가 인자로 전달된 함수를 기능이 추가된 새로운 함수로 만들고 이 함수를 반환한다.

def smile():
    print('^_^')

def confused():
    print('@_@')

# 위 함수들의 결과를 'emoticon!'이라는 글이 위, 아래에 위치하도록 꾸며줄 수 있다. 


def deco(func):  # 데코레이터 함수
    def wrap_func():
        print('emoticon!')
        func()
        print('emoticon!')
        
    return wrap_func


smile_deco = deco(smile)
smile_deco()

'''
emoticon!
^_^
emoticon!
'''

confused_deco = deco(confused)
confused_deco()

'''
emoticon!
@_@
emoticon!
'''

# 데코레이터 함수(deco)가 인자로 전달된 함수(smile, confused)에 기능을 추가

 

■ [전달 인자가 있는 함수 기반의 데코레이터]

def adder2(n1, n2):
    return n1 + n2

def adder3(n1, n2, n3):
    return n1 + n2 + n3


def adder_deco(func):  # 데코레이터 함수
    def wrap_func(*args):  # 전달 인자를 튜플로 받는다.(튜플패킹)
        print(*args, sep = ' + ', end = ' ')  # 튜플언패킹
        print('= {0}'.format(func(*args)))  # 튜플언패킹
        
    return wrap_func


adder2 = adder_deco(adder2)  
# adder2 함수 객체를 인자로 넘기고, wrap_func 함수 객체 리턴

### 리턴된 함수 ###
#wrap_func(*args):
#    print(*args, sep = ' + ', end = ' ')
#    print('= {0}'.format(func(*args)))  

adder2(3, 4)  # 3 + 4 = 7
# wrap_func(3, 4)와 같고, 내부 코드가 실행됨


adder3 = adder_deco(adder3)
adder3(1, 2, 3)  # 1 + 2 + 3 = 6

 

good4me.co.kr

 

■ [전달 인자 2개 받는 경우의 데코레이터]

def deco_func(func):
    def wrap_func(*args, **kwargs):
        print('{} 함수 호출 직전'.format(func.__name__))
        return func(*args, **kwargs)  # func() 호출 실행 후 리턴
    
    return wrap_func


def param_func(p1, p2):
    print('내부 함수가 "{0}", "{1}" 매개변수를 받아 실행됨'.format(p1, p2))


param_f = deco_func(param_func)
param_f('토마토', 10)

# param_func 함수 호출 직전
# 내부 함수가 "토마토", "10" 매개변수를 받아 실행됨

 

■ [@ 기반으로 데코레이터 만들기]

def deco2(func):
    def wrap_func():
        print('emoticon!')
        func()
        print('emoticon!')
        
    return wrap_func


#def smile2():
#    print('^_^')

#smile_deco2 = deco2(smile2)
#smile_deco2()

# 위 주석 코드 대신에 아래처럼 @ 기호를 사용해도 동일한 결과임 

@deco2
def smile2():
    print('^_^')

smile2()
'''
emoticon!
^_^
emoticon!
'''

 

# 임의 숫자 여러 개 전달 시 더하기

def adders(func):  # 데코레이터 함수
    def wrap_func(*args):
        print(*args, sep = ' + ', end = ' ')
        print('= {0}'.format(func(*args)))
    return wrap_func


@adders   
def adders(*args):
    return sum([n for n in args])


import random

n = random.sample(range(1, 100), random.randint(2, 10))

adders(*n)  # 81 + 79 + 57 + 93 + 43 + 12 + 90 = 455


 

[참고 자료] 윤성우의 열혈파이썬 중급편

 

댓글