데코레이터
함수의 호출 전과 후의 코드를 추가로 실행 가능
함수의 입력 인자, 반환 값, 함수에서 발생한 오류 접근
함수의 의미 강화, 디버깅, 함수 등록의 기능에 유용하다.
기호@
def trace(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
print(f'{func.__name__}({args!r}, {kwargs!r})'
f'-> {result!r}')
return result
return wrapper
@trace
def fibonacci(n):
"""n번째 피보나치 수를 반환한다."""
if n in (0,1):
return n
return (fibonacci(n-2) + fibonacc(n-1))
"""
@기호 사용은 fibonacci = trace(fibonacci)
"""
fibonacci(4)
#결과
fibonacci((0,),{}) ->0
wapper((0,),{})->0
fibonacci((1,),{}) ->1
wapper((1,),{})->1
fibonacci((2,),{}) ->1
wapper((2,),{})->1
fibonacci((1,),{}) ->1
wapper((0,),{})->0
fibonacci((0,),{}) ->0
wapper((1,),{})->1
fibonacci((1,),{}) ->1
wapper((1,),{})->1
fibonacci((2,),{}) ->1
wapper((2,),{})->1
fibonacci((3,),{}) ->2
wapper((3,),{})->2
fibonacci((4,),{}) ->3
wapper((4,),{})->3
#부작용: 데코레이터가 반환한 함수의 이름은 fibonacci가 아니다
부작용 해결
부작용 해결
wraps 도우미 함수 사용
#wraps를 wrapper함수에 적용하면 wraps가 데코레이터 내부에 들어가는 함수에서
#중요한 메타데이터 복사하여 wrapper함수 적용
from functools import wraps
def trace(func):
@wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
print(f'{func.__name__}({args!r}, {kwargs!r})'
f'-> {result!r}')
return result
return wrapper
@trace
def fibonacci(n):
"""n번째 피보나치 수를 반환한다."""
if n in (0,1):
return n
return (fibonacci(n-2) + fibonacc(n-1))
#help함수 실행
help(fibonacci)
#Help on function fibonacci in module __main__:
fibonacci(n) #n번째 피보나치 수를 반환
#pickle 객체 직렬화도 가능
print(pickle.dumps(fibonacci))