파이썬은 함수에 적용할 수 있는 데코레이터를 정의하는 특별한 구문을 제공한다.
데코레이터는 자신이 감싸고 있는 함수가 호출되기 전과 후에 코드를 추가로 실행해준다.
이는 데코레이터가 자신이 감싸고 있는 함수의 입력 인자, 반환값, 함수에서 발생한 오류에 접근할 수 있다는 뜻이다.
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) + fibonacci(n - 1))
fibonacci(4)
fibonacci((0,), {}) -> 0 fibonacci((1,), {}) -> 1 fibonacci((2,), {}) -> 1 fibonacci((1,), {}) -> 1 fibonacci((0,), {}) -> 0 fibonacci((1,), {}) -> 1 fibonacci((2,), {}) -> 1 fibonacci((3,), {}) -> 2 fibonacci((4,), {}) -> 3
3
fibonacci = trace(fibonacci)
fibonacci(4)
fibonacci((0,), {}) -> 0 wrapper((0,), {}) -> 0 fibonacci((1,), {}) -> 1 wrapper((1,), {}) -> 1 fibonacci((2,), {}) -> 1 wrapper((2,), {}) -> 1 fibonacci((1,), {}) -> 1 wrapper((1,), {}) -> 1 fibonacci((0,), {}) -> 0 wrapper((0,), {}) -> 0 fibonacci((1,), {}) -> 1 wrapper((1,), {}) -> 1 fibonacci((2,), {}) -> 1 wrapper((2,), {}) -> 1 fibonacci((3,), {}) -> 2 wrapper((3,), {}) -> 2 fibonacci((4,), {}) -> 3 wrapper((4,), {}) -> 3
3
print(fibonacci)
<function trace.<locals>.wrapper at 0x7f21d86579d0>
help(fibonacci)
Help on function wrapper in module __main__: wrapper(*args, **kwargs)
import pickle
pickle.dumps(fibonacci)
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-24-689374fb5a49> in <module> 1 import pickle 2 ----> 3 pickle.dumps(fibonacci) AttributeError: Can't pickle local object 'trace.<locals>.wrapper'
문제를 해결하는 방법은 functools 내장 모듈에 정의된 waps 도우미 함수를 사용하는 것이다.
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) + fibonacci(n - 1))
help(fibonacci)
Help on function fibonacci in module __main__: fibonacci(n) n번쨰 피보나치 수를 반환한다.
하지만 키워드 인자와 디폴트 값은 예상대로 잘 작동한다.
import pickle
pickle.dumps(fibonacci)
b'\x80\x04\x95\x1a\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main__\x94\x8c\tfibonacci\x94\x93\x94.'