Python에서 데코레이터를 만들고 사용하는 방법

Python에서 데코레이터를 작성하고 적용하는 방법을 알아보세요. 래핑 기능, 동작 수정, 인수 처리 및 래핑을 통한 메타데이터 보존을 마스터하세요.

Editor에서 이 솔루션을 사용해 보세요.

개요

데코레이터는 Python의 가장 우아하고 강력한 구문 기능 중 하나로, 코드를 영구적으로 변경하지 않고도 함수나 클래스의 동작을 수정할 수 있습니다. 실행 시간 로깅, 사용자 인증 시행, 결과 캐싱(메모) 및 API 엔드포인트 감사와 같은 교차 문제에 널리 사용됩니다.

내부적으로 데코레이터는 다른 함수를 인수로 사용하고 일부 사용자 정의 논리를 주입하는 중첩 래퍼 함수를 정의하고 이 래퍼 함수를 반환하는 고차 함수입니다. Python은 '@' 기호를 사용하여 함수에 데코레이터를 적용하여 시각적으로 우아하게 만드는 깔끔한 단축 구문을 제공합니다.

데코레이터를 작성할 때 일반적으로 데코레이팅된 함수가 원하는 수의 위치 및 키워드 인수를 지원하기를 원할 것입니다. `*args` 및 `**kwargs`를 허용하고 이를 대상 함수에 전달하도록 중첩된 래퍼 함수를 ​​설계하면 이를 달성할 수 있습니다. 또한 원래 함수의 독스트링과 이름 메타데이터를 보존하려면 래퍼 함수에서 'functools.wraps'를 사용해야 합니다.

코드 및 실행 출력

이 스크립트는 로깅 데코레이터를 작성하고 입력, 출력 및 메타데이터를 검사하는 함수를 래핑하는 방법을 보여줍니다.

from functools import wraps

# 1. Defining a decorator
def log_execution(func):
    @wraps(func) # Preserves original function metadata
    def wrapper(*args, **kwargs):
        print(f"[Log] Calling function: {func.__name__} with args: {args}")
        result = func(*args, **kwargs)
        print(f"[Log] Finished {func.__name__}. Result: {result}")
        return result
    return wrapper

# 2. Applying the decorator using @ syntax
@log_execution
def add_numbers(a, b):
    """Adds two numbers and returns the sum."""
    return a + b

# 3. Invoking the decorated function
sum_result = add_numbers(15, 25)
print("Sum Result:", sum_result)

# Verifying metadata preservation
print("Docstring preserved:", add_numbers.__doc__)
터미널 출력
[Log] Calling function: add_numbers with args: (15, 25)
[Log] Finished add_numbers. Result: 40
Sum Result: 40
Docstring preserved: Adds two numbers and returns the sum.

단계별 구현

  • 대상 함수를 인수로 사용하는 외부 데코레이터 함수를 정의합니다.
  • 원본 메타데이터를 보호하려면 중첩된 래퍼 함수에 @functools.wraps(func)를 가져와 적용하세요.
  • 입력 변수를 캡처하고 로직을 삽입하고 대상 함수를 호출하려면 래퍼(*args, **kwargs)를 구현하세요.
  • 데코레이터 헤더 블록에서 래퍼 함수 객체를 반환합니다.
  • 대상 함수 시그니처 바로 위에 @ decorator_name을 사용하여 데코레이터를 적용합니다.

자주 묻는 질문

데코레이터 내부에 @functools.wraps가 필요한 이유는 무엇입니까?

랩이 없으면 데코레이팅된 함수는 원래 ID를 잃습니다(해당 __name__ 및 __doc__ 속성은 중첩된 래퍼 함수의 속성으로 대체됨). 이로 인해 디버깅 및 코드 검사가 어려워집니다.

단일 함수에 여러 데코레이터를 적용할 수 있나요?

예! 여러 개의 @ 줄을 쌓아서 데코레이터를 연결할 수 있습니다. Python은 이를 상향식으로 적용합니다(함수 정의에 가장 가까운 것이 먼저 실행됩니다).

관련 주제

권장 Python 리소스

관련 대화형 튜토리얼, 치트 시트, 코드 비교를 통해 지식을 확장하세요.