Decorator 1
어떤 함수에 있는 핵심코드를 수행하기 이전과 이후에 뭔가 작업을 하고 싶어
스프링 AOP 적용과 비슷하게 작업을 할수 있는게 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 28 29 30 | #-*- coding: utf-8 -*- ''' - decorator 학습하기 ''' def helloBye(func): def wrapper(): print "hello!" # helloBye 의 인자로 전달된 함수를 호출 func() print "bye!" return wrapper @helloBye def f1(): print u"f1() 함수를 수행했습니다." @helloBye def f2(): print u"f2() 함수를 수행했습니다." @helloBye def f3(): print u"f3() 함수를 수행했습니다." if __name__ == '__main__': f1() print "-----" f2() print "-----" f3() | cs |
helloBye 라는 함수 안에 wrapper 라는 함수가 정의 되어 있어
helloBye 라는 함수는 wrapper라는 함수를 리턴해줘
그 warpper 안에서 인자로 전달된 함수를 호출하면 f1, f2, f3의 메인 함수가 수행되는데
그 앞뒤에서 뭔가 작업을 해줄 것을 정의해 주고
@helloBye 처럼 함수 이름과 똑같이 붙여주는 것이 Decorator 임
함수를 장식해 주는 것이라고 보면 됌
데코레이터를 만들어 주고 원하는 곳에 적용을 시키는 거야
데코레이터 장식을 하면 전달된 값( f1 )이 함수에 들어가서
데코레이터 함수 안에서 콜( func() ) 하는 것
Decorator 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #-*- coding: utf-8 -*- # 어떤 인자의 형태도 받아줄수 있는 함수 def test(*args, **kwargs): print args print kwargs print "--- test() ---" if __name__ == '__main__': test(1) test(1,2) test("a","b","c") test(name="gura") test(isMan=True) test(name="monkey", isMan=False) test("a", "b", name="cat", isMan=True) | cs |
*args 는 아규먼트
*args 는 tuple(소괄호에 컴마로 구분되어 지는 것)로 받아져
**kwargs 는 키워드 아규먼트
**kwargs 는 dict(중괄호 안에 key : value 형태로 이루어져 있는 것) 로 받아져
위 예제를 보면 함수의 인자로 *args와 **kwargs를 가져가면
그 함수는 인자를 전달하든 안하든, 나열을 하든 키워드로 전달을 하든 다 받아줄 수 있어
# 어떤 인자의 형태도 받아줄수 있는 함수
def test(*args, **kwargs):
pass
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 28 29 30 31 32 33 34 35 36 37 | #-*- coding: utf-8 -*- # 어떤 인자의 형태도 받아줄수 있는 함수 def test(*args, **kwargs): print args print kwargs print "--- test() ---" # 데코레이터 함수 정의하기 def auth(func): def wrapper(*args, **kwargs): # decorator 가 적용된 함수에 전달된 인자를 얻어올수 있다 print args, kwargs # kwargs 는 dict type 이므로 kwargs["key"] 형태로 참조 print kwargs["name"], "auth !" func(*args, **kwargs) print kwargs["name"], "success !" return wrapper @auth def updateUser(name): print name, u"의 정보를 업데이트 합니다." @auth def deleteUser(name): print name, u"의 정보를 삭제 합니다." if __name__ == '__main__': # test(1) # test(1,2) # test("a","b","c") # test(name="gura") # test(isMan=True) # test(name="monkey", isMan=False) # test("a", "b", name="cat", isMan=True) updateUser(name="gura") deleteUser(name="monkey") | cs |
@auth 함수가 func 에 담기고
전달된 인자는 args, kwargs 에 담김
데코레이터를 함수 형태로 만들어서 적용을 시킨 것임
함수형태로 만드니까 뭔가 뚱뚱한거 같아
그래서 간단하게 할수 있는 방법이 클래스를 이용한 방법이 있어
Decorator 3
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 28 29 30 31 32 33 34 35 | #-*- coding: utf-8 -*- ''' - decorator 를 class 로 정의하면 더 깔끔하다. ''' # decorator 역할을 할 class 정의하기 class HelloBye: # 생성자 def __init__(self, f): # 인자로 전달된 함수를 func 라는 필드에 저장하기 self.func=f # 객체를 call 했을때 호출되는 메소드 def __call__(self, *args, **kwargs): print "hello!" self.func(*args, **kwargs) # 멤버 메소드 호출하기 self.sing() self.dance() print "bye!" def sing(self): print u"노래를 불러요" def dance(self): print u"춤을 춰요" @HelloBye def test1(): print "test!() called" if __name__ == '__main__': test1() | cs |
test!() called 이전과 이후에 동작을 잘 하는 것을 확인 할 수 있어
데코레이터를 class 형태로 정의하기 위해 정해진 폼
파이선 에선 동적으로 멤버필드를 원하는 시점에 만들수도 있어
(self.func=f)
__call__ 이 함수는
아까 만들었던 wrapper 함수 정도라고 생각하면 됌
데코레이터는 클래스 형태로 만들수 있고 함수형태로 만들수 있는데
클래스 형태가 훨씬 나아
Decorator 4
데코레이터를 클래스로 만들어 두면
다른 패키지에 적당하게 만들어 두고
임포트 해서 끌어와서 사용도 가능 함
패키지 하나에 MyDeco.py 하나 만들어 주고
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #-*- coding: utf-8 -*- ''' deco 패키지의 MyDeco.py 파일에 HelloBye 데코레이터 클래스 정의하기 ''' # decorator 역할을 할 class 정의하기 class HelloBye: # 생성자 def __init__(self, f): # 인자로 전달된 함수를 func 라는 필드에 저장하기 self.func=f # 객체를 call 했을때 호출되는 메소드 def __call__(self, *args, **kwargs): print "hello!" self.func(*args, **kwargs) # 멤버 메소드 호출하기 self.sing() self.dance() print "bye!" def sing(self): print u"노래를 불러요" def dance(self): print u"춤을 춰요" # decorator 역할을 할 class 정의하기 class Auth: # 생성자 def __init__(self, f): # 인자로 전달된 함수를 func 라는 필드에 저장하기 self.func=f # 객체를 call 했을때 호출되는 메소드 def __call__(self, *args, **kwargs): print u"인증 작업을 해요." self.func(*args, **kwargs) print u"정상 처리 되었습니다." | cs |
이렇게 코딩해 주고
다른 패키지에서 이런식으로 임포트를 해서 실행시켜 주면
원하는 대로 잘 작동을 하는 것을 확인할 수 있다.
'FrameWork > Python' 카테고리의 다른 글
파이썬 File 관리 (0) | 2017.08.11 |
---|---|
파이썬 예외처리 try / except (0) | 2017.08.11 |
파이썬 lambda (2) | 2017.08.10 |
파이썬 Extends(상속) (2) | 2017.08.10 |
파이썬 Class (0) | 2017.08.10 |