본문 바로가기
Python/Python FAQ

Python functools.wraps는 무엇을 하는 것인가요?, What does functools.wraps do?

by 베타코드 2023. 6. 7.
반응형

질문


다른 질문에 대한 답변에 댓글에서, 누군가는 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' 출력
반응형

댓글