python에서는 @라는 키워드를 이용해서 decorator라는 기능을 쓰면 함수의 기능을 확장하여 사용 할 수 있다.
python에서도 javascript와 동일하게 함수를 일급객체 취급을 한다. 즉 함수를 변수에 담아서 인자로 넘길 수 있다는 의미가 된다.
이제 decorator의 기능에 대해서 알아보자.
함수를 다른 함수의 기능을 덧 붙일수 있고, 클래스의 기능을 덧 붙일수 있다.
첫번쨰로 함수의 기능을 덧 붙여보자.
1. function
p.py
1
2
3
4
5
6
7
8
9
10
11
12
13
|
def decorator_test(func):
def new_func():
print ("Begin")
func()
print ("End")
return new_func
@decorator_test
def ppp():
print('test')
ppp()
| cs |
p1.py
1
2
3
4
5
6
7
8
9
10
11
12
13
|
def decorator_test(func):
def new_func():
print ("Begin")
func()
print ("End")
return new_func
# @decorator_test
def ppp():
print('test')
test = decorator_test(ppp)
test()
| cs |
$python p.py
>>> Begin
test
End
$python p1.py
>>> Begin
test
End
두 코드를 실행을 해보면 실행결과가 똑같다.
아마 decorator를 보다 클로저에 익숙한 개발자라면 p.py코드보단 p1.py가 더 익숙할 것이다.
python에서는 decorator를 사용하면 p.py를 p1.py와 같은 방식으로 코드가 동작한다.
2. class
p.py
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class decorator_test(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
name = kwargs.get('name').lower()
self.func(name)
@decorator_test
def good(name):
print("good ", name)
good(name='mung')
| cs |
$python p.py
>>> good mung
위와 같이 실행이 된다.
클래스에서는 데코레이터를 사용하면 @[클래스] 해당 클래스를 아래에 있는 함수를 인자로 넘겨 init을 실행을 한다.
이후 해당 함수를 실행을 하면 클래스명으로 호출이 되어 __call__이 호출이 된다.
데코레이터는 인자도 넘길 수 있다.
p.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
def out(param1, param2):
def decorator_test(func):
def new_func():
print ("Begin", param1)
func()
print ("End", param2)
return new_func
return decorator_test
@out(1,2)
def ppp():
print('test')
ppp()
| cs |
$python p.py
>>> Begin 1
test
End2
데코레이터에서 인자를 넘기기 위해서는 parameter를 받는 함수로 감싸주어야 한다.
데코레이터로 이것저것 테스트 하다가 발견한 것인데
1
2
3
4
5
6
7
8
9
10
|
def decorator_test():
def new_func(func):
print ("Begin")
func()
print ("End")
return new_func
@decorator_test()
def ppp():
print('test')
| cs |
$python p.py
>>> Begin
test
End
위 코드에서는 어느 함수도 호출 하는 것이 없는데 바로 실행이 된다.
그럼 먼가 복잡해 보이는 데코레이터를 왜 이용을 할 까????
1
2
3
4
5
6
7
8
9
10
11
|
def process1():
start = time.time()
for i in range(10000):
pass
end = time.time()
def process2():
start = time.time()
for i in range(10000):
pass
end = time.time()
| cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
def decorator_test(func):
def new_func():
start = time.time()
func()
end = time.time()
print(end - start)
return new_func
@decorator_test
def proccess1():
for i in range(10000):
pass
@decorator_test
def proccess2():
for i in range(10000):
pass
| cs |
위코드를 아래 처럼 바꿀 수 있다.
위코드와 다르게 시간은 찍어주는 코드를 재사용하여 사용하고 있다.
댓글
댓글 쓰기