-
[코딩도장] day29. 파이썬 데코레이터(2/2)IT/파이썬 2020. 9. 26. 16:14
■ 들어가기
- 파이썬 코딩 도장 (남재윤/길벗). 을 공부하며 정리하는 블로그
▶ Unit42. 데코레이터 사용하기
- 42.1 데코레이터 만들기
- 42.2 매개변수와 반환값을 처리하는 데코레이터 만들기
- 42.3 매개변수가 있는 데코레이터 만들기
- 42.4 클래스로 데코레이터 만들기
- 42.5 클래스로 매개변수와 반환값을 처리하는 데코레이터 만들기
>> 42.3 매개변수가 있는 데코레이터 만들기 <<
- 매개변수가 있는 데코레이터는 값을 지정해서 동작 바꿀 수 있음
소스 (decorator_parameter.py) 결과 def is_multiple(x) : # 데코레이터가 사용할 매개변수 지정
def real_decorator(func) : # 호출할 함수를 매개변수로 받음
def wrapper(a, b) : # 호출할 함수의 매개변수와 똑같이 지정
r = func(a, b) # func를 호출하고 반환값을 변수에 저장
if r % x == 0 : # func의 반환값이 x의 배수인지 확인
print('{0}의 반환값은 {1}의 배수입니다.'.format(func.__name__, x))
else :
print('{0}의 반환값은 {1}의 배수가 아닙니다.'.format(func.__name__, x))
return r # func의 반환값을 반환
return wrapper # wrapper 함수 반환
return real_decorator # real_decorator 함수 반환
@is_multiple(3) # @데코레이터(인수)
def add(a, b) :
return a + b
print(add(10, 20))
print(add(2, 5))add의 반환값은 3의 배수입니다.
30
add의 반환값은 3의 배수가 아닙니다.
7- 앞서 데코레이터 만들 때 함수 안에 함수를 하나만 만들었는데.
- 매개변수가 있는 데코레이터를 만들 때는 함수를 하나 더 만들어야 함. 즉, 함수 2개 생성 필요
def is_multiple // 데코레이터 함수로 매개변수 x 지정
def real_decorator // 실제 데코레이터 역할하는 함수. 호출할 함수를 매개변수로 받음
def wrapper // 래퍼함수. 실제 호출할 함수와 동일한 매개변수 지정
>> 42.4 클래스로 데코레이터 만들기 <<
- 클래스로 데코레이터를 구현 시,
1) 먼저 __init__ 메서드를 만들고 호출할 함수를 초깃값으로 받고
2) 인스턴스를 함수처럼 호출하게 해주는 __call__ 메서드를 구현해야 함
소스 (decorator_class.py) 결과 class Trace :
def __init__(self, func) : # 호출할 함수를 인스턴스의 초깃값으로 받음
self.func = func # 호출할 함수를 속성 func에 저장
def __call__(self) :
print(self.func.__name__, '함수 시작') # __name__으로 함수 이름 출력
self.func() # 속성 func에 저장된 함수 호출
print(self.func.__name__, '함수 끝')
@Trace # @데코레이터
def hello() :
print('hello')
hello() # 함수를 그대로 호출hello 함수 시작
hello
hello 함수 끝>> 42.5 클래스로 매개변수와 반환값을 처리하는 데코레이터 만들기 <<
- 클래스로 만든 데코레이터도 매개변수와 반환값 처리 가능
소스 (decorator_class_param_return.py) 결과 class Trace :
def __init__(self, func) : # 호출할 함수를 인스턴스의 초깃값으로 받음
self.func = func # 호출할 함수를 속성 func에 저장
def __call__(self, *args, **kwargs) : # 호출할 함수의 매개변수를 처리
r = self.func(*args, **kwargs) # self.func에 매개변수를 넣어 호출한 뒤 반환값을 변수에 저장
print('{0}(args={1}, kwargs={2}) -> {3}'.format(self.func.__name__, args, kwargs, r))
return r
@Trace # @데코레이터
def add(a, b) :
return a + b
print(add(10, 20))
print(add(a=10, b=20))add(args=(10, 20), kwargs={}) -> 30
30
add(args=(), kwargs={'a': 10, 'b': 20}) -> 30
30- 위의 예제에서는 위치 인수와 키워드 인수를 모두 처리하는 가변 인수로 구현하였으나
- 고정된 매개변수를 사용할 때는 "def __call__(self, a, b) : " 처럼 구현 가능
[REMIND] 위치 인수?
- 함수에 인수를 순서대로 넣는 방식
- 위치 인수를 사용하는 함수는 리스트(튜플) 앞에 *(애스터리스크)를 붙혀서 리스트 언패킹으로 넣을 수 있음
def 함수이름(매개변수, 매개변수2) : # 위치 인수를 사용하는 함수
코드
함수(*리스트) # 리스트 언패킹
함수(*튜플) # 튜플 언패킹- 위치 인수를 사용하는 가변 인수 함수는 매개변수 앞에 *를 붙여서 만듦
def 함수이름(*매개변수) : # 위치인수를 사용하는 가변 인수 함수 (일반적으로 *args 형태로 작성, 타입: 튜플)
코드
함수(인수1, 인수2) # 인수 여러 개를 직접 넣기
함수(*리스트) # 리스트 언패킹
함수(*튜플) # 튜플 언패킹[REMIND] 키워드 인수?
- 함수에 넣는 인수에 이름(키워드)를 붙이는 방식
- 키워드 인수는 딕셔너리 앞에 **(애스터리스크 두 개)를 붙여서 딕셔너리 언패킹으로 넣을 수 있음
함수(키워드1=값1, 키워드2=값2) # 함수를 키워드 인수 방식으로 호출
함수(**딕셔너리) # 딕셔너리 언패킹- 키워드 인수를 사용하는 가변 인수 함수는 매개변수 앞에 **를 붙여서 만듦
def 함수이름(**매개변수) : # 키워드 인수를 사용하는 가변 인수 함수 (일반적으로 **kwargs 형태로 작성, 타입: 딕셔너리)
코드
함수(키워드1=값1, 키워드2=값2) # 키워드 인수를 직접 넣기
함수(**딕셔너리) # 딕셔너리 언패킹1. 클래스로 매개변수가 있는 데코레이터 만들기
소스 (decorator_class_parameter.py) 결과 class IsMultiple :
def __init__(self, x) : # 데코레이터가 사용할 매개변수를 초깃값으로 받음
self.x = x
def __call__(self, func) : # 호출할 함수를 매개변수로 받음
def wrapper(a, b) : # 호출할 함수의 매개변수와 똑같이 지정 (가변인수로 지정 가능)
r = func(a, b) # func를 호출하고 반환값을 변수에 저장
if r % self.x == 0 :# func의 반환값이 self.x의 배수인지 확인
print('{0}의 반환값은 {1}의 배수입니다.'.format(func.__name__, self.x))
else :
print('{0}의 반환값은 {1}의 배수가 아닙니다.'.format(func.__name__, self.x))
return r # func의 반환값을 반환
return wrapper # wrapper 함수 반환
@IsMultiple(3) # @데코레이터(인수)
def add(a, b) :
return a + b
print(add(10, 20))
print(add(2, 5))add의 반환값은 3의 배수입니다.
30
add의 반환값은 3의 배수가 아닙니다.
7- 보통 데코레이터는 프로그램의 버그를 찾는 디버깅, 함수의 성능 측정, 함수 실행 전에 데이터 확인 등에 활용됨
'IT > 파이썬' 카테고리의 다른 글
[코딩도장] day32. 파이썬 모듈과 패키지 사용하기 (0) 2020.10.06 [코딩도장] day30. 파이썬 정규표현식 사용하기 - re, *, +, match (0) 2020.09.29 [코딩도장] day28. 파이썬 데코레이터(1/2) - @데코레이터, def데코레이터 (0) 2020.09.22 [코딩도장] day27. 파이썬 코루틴 - next, send, yield (0) 2020.09.21 [코딩도장] day27. 파이썬 제너레이터 사용하기 - yield (0) 2020.09.21