본문 바로가기

Python/Python Basic

Decorator_02 (파라미터가 있는 함수 decorator & 모든 함수에 대한 decorator)

Decorator

- 기존 함수에 기능을 추가하여 새로운 함수를 만듬

- Closure function을 활용

- https://www.python.org/dev/peps/pep-0318/

- decorator 사용 이유는? 함수 혹은 메쏘드에 새로운 기능을 추가하기 위해!

- 그렇다면 왜 소스 코드를 수정하지 않는가? 여러 함수에 동일한 기능을 추가할 수 있다.

  예를 들면, 모든 함수에 전달된 파라미터의 유효성 검사가 필요하다고 가정했을때, 유효성 검사 코드가 각 함수마다 복사되면 수정의 어려움이 존재한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# decorator 함수 정의
def decorate_func(function):
    def inner():
        print('decoration added')
        function()
    return inner
 
def simple():
    print('simpel function')
    
# 일반 함수 호출
simple()
 
print('='*20)
 
# simple 함수에 기능을 추가한(decorate 한) decorated 함수
decorated = decorate_func(simple)
# 결과가 decoration 됨
decorated()
 
==================<<실행결과>>==================
 
simpel function
====================
decoration added
simpel function
 
cs

 

 

'@'심볼 사용

- decorator를 생성하기 위한 syntactic sugar (문법적 편의성)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# decorator 함수 정의
def decorate_func(function):
    def inner():
        print('decoration added')
        function()
    return inner
 
def simple():
    print('simple function')
    
# 사실 귀찮고, python 답지 않은 문법임
simple = decorate_func(simple)
simple()
 
==================<<실행결과>>==================
 
decoration added
simple function
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# decorator 함수 정의
def decorate_func(fn):
    def inner():
        print('decoration added')
        fn()
    return inner
 
# 아래와 같이 @를 사용하여 decoration 가능!
# 기능을 추가하는 것이라고 이해하면 된다.
@decorate_func
def simple():
    print('simple function')
    
# 결과가 decorated 됨!
simple()
 
==================<<실행결과>>==================
 
decoration added
simple function
cs

 

 

파라미터가 있는 함수 Decorator

- 중첩함수에 꾸미고자 하는 함수와 동일하게 파라미터를 가져가면 됨

 

case1) '@' 기호를 쓰지 않은 경우

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def decorate_divide(fn):
    def wrapper(a, b):
        if b == 0:
            print('zero cannot be divided!')
            return
        return fn(a, b)
    return wrapper
 
def divide(a, b):
    return a / b
 
divide = decorate_divide(divide)
print(divide(93))
print(divide(90))
 
==================<<실행결과>>==================
 
3.0
zero cannot be divided!
None
cs

 

case2) '@' 기호를 쓰는 경우

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def decorate_divide(fn):
    def wrapper(a, b):
        if b == 0:
            print('zero cannot be divide!')
            return
        return fn(a, b)
    return wrapper
 
# '@' 기호를 아래와 같이 사용 할 것!
@decorate_divide
def divide(a, b):
    return a / b
 
print(divide(90))
print('='*20)
print(divide(817))
 
==================<<실행결과>>==================
 
zero cannot be divide!
None
====================
11.571428571428571
cs

 

 

모든 함수에 대한 Decorator

- 모든 함수의 파라미터는 (*args, ***kwargs)로 표현 가능하다. 따라서 내부함수의 파라미터를 (*args, ***kwargs)로 구성하면 어떠한 함수도 decoration 가능

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def general_decorator(fn):
    def wrapper(*args, **kwargs):
        print('function is decorated..')
        return fn(*args, **kwargs)
    return wrapper
 
@general_decorator
def add(a, b):
    return a + b
 
@general_decorator
def print_hello():
    print('hello')
    
print(add(45))
print('=' * 20)
print_hello()
 
==================<<실행결과>>==================
 
function is decorated..
9
====================
function is decorated..
hello
cs

 

반응형