반응형
질문
다른 질문에 대한 답변에 댓글에서, 누군가는 functools.wraps
가 무엇을 하는지 확실하지 않다고 말했습니다. 그래서, 나는 이 질문을 하여 나중에 StackOverflow에서 참고할 기록이 있도록 하고 싶습니다: functools.wraps
는 정확히 무엇을 하는가요?
답변
데코레이터를 사용하면 하나의 함수를 다른 함수로 대체합니다. 다시 말해, 데코레이터를 사용하는 경우
def logged(func):
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging
위와 같은 데코레이터가 있다면
@logged
def f(x):
"""does some math"""
return x + x * x
이 코드는
def f(x):
"""does some math"""
return x + x * x
f = logged(f)
와 정확히 같습니다. 그리고 함수 f
가 함수 with_logging
으로 대체됩니다. 그러나 이렇게 하면
print(f.__name__)
이 코드를 실행하면 새로운 함수의 이름인 with_logging
이 출력됩니다. 사실, f
의 도움말 문자열을 보면 빈 문자열이 나옵니다. 이는 with_logging
에 도움말 문자열이 없기 때문입니다. 또한, 이 함수에 대한 pydoc 결과를 보면 인수 x
를 받는 것이 아니라 *args
와 **kwargs
를 받는 것으로 나옵니다.
데코레이터를 사용하면 항상 이러한 함수 정보를 잃어버린다면 심각한 문제가 될 것입니다. 이것이 functools.wraps
가 필요한 이유입니다. functools.wraps
는 데코레이터에서 사용하는 함수를 가져와 함수 이름, 도움말 문자열, 인수 목록 등의 기능을 추가합니다. 또한, wraps
자체가 데코레이터이므로 다음 코드는 올바른 결과를 출력합니다:
from functools import wraps
def logged(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging
@logged
def f(x):
"""does some math"""
return x + x * x
print(f.__name__) # 'f' 출력
print(f.__doc__) # 'does some math' 출력
반응형
댓글