functools.wraps는 보통 python fucntion을 wrapping할 때 원래 function의 정보들을 유지 시키기 위해서 사용된다.
간단한 wrapper 코드를 보자.
import functools def print_iam_wrapper(method): @functools.wraps(method) ----- 1 def wrapper(*args, **kwargs): ----- 2 print "I'm wrapper" return method(*args, **kwargs) return wrapper @print_iam_wrapper def iam_func(): print 'iam_func' print iam_func.__name__ ----- 3 iam_func() ----- 4 |
여기서 1번을 제거해도 4번의 결과는 같다. 하지만 3번의 결과는 다르다.
wraps가 하는 일은 wraps, update_wrapper, partial 코드를 살펴보면 이해가 간다.
(3개의 function에 대한 코드는 아래에 두겠다.)
1번 decorator가 실행될때 method가 넘어가서 넘어오는 것은 결국 wraps의 결과인 partial() 리턴값인데 이것은 newfunc 이다. 그렇다면 1번은 @newfunc가 되었다고 볼 수 있다.
그리고 @newfunc에 파라미터로 넘어가는 것은 아래있는 wrapper function이 된다. 이때 newfunc은 update_wrapper를 실행하고 있으므로 이는 또한 @update_wrapper와 같다. 다만 이때 wrapped로 처음에 전달된 method 즉 iam_func이 넘어가 있을 것이다. 결국 의미는 wrapped에 설정되어있는 '__module__', '__name__', '__doc__', '__dict__' attritbute를 wrapper에 셋팅하여 던져주는 것이다.
* 참고) update_wrapper, wraps, partial
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__') WRAPPER_UPDATES = ('__dict__',) def update_wrapper(wrapper, wrapped, assigned = WRAPPER_ASSIGNMENTS, updated = WRAPPER_UPDATES): for attr in assigned: setattr(wrapper, attr, getattr(wrapped, attr)) for attr in updated: getattr(wrapper, attr).update(getattr(wrapped, attr, {})) # Return the wrapper so this can be used as a decorator via partial() return wrapper def wraps(wrapped, assigned = WRAPPER_ASSIGNMENTS, updated = WRAPPER_UPDATES): return partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated) |
'python' 카테고리의 다른 글
gunicorn vs uwsgi (0) | 2017.01.20 |
---|---|
flask async response (0) | 2017.01.04 |
Apple Push Notification Service(APNs) python modules (0) | 2015.04.07 |
Getting specific timezone timestamp from time string (0) | 2015.01.20 |
Shallow copy VS Deep copy (0) | 2014.08.27 |