Please Enable JavaScript!
Gon[ Enable JavaScript ]

파이썬 Python 데코레이터 활용하기

파이썬 Python
반응형

 

데코레이터는 파이썬에서 함수 또는 메서드를 수정하지 않고도 추가 기능을 부여할 수 있는 강력한 기능입니다. 주로 코드의 재사용성, 유지보수성, 가독성을 높이는 데 사용됩니다. 데코레이터는 기존 함수에 기능을 "랩핑"하여 호출 전후로 특정 작업을 수행하도록 합니다.

 


1. 데코레이터의 기본 구조

데코레이터는 다른 함수를 인자로 받아 새로운 함수를 반환하는 함수로 정의됩니다.

def my_decorator(func):
    def wrapper():
        print("함수 실행 전")
        func()
        print("함수 실행 후")
    return wrapper

설명: my_decorator 함수는 func를 받아 wrapper라는 새 함수를 반환합니다. wrapper는 func를 호출 전후에 추가 기능을 실행합니다.


2. 데코레이터 적용 방법

데코레이터는 함수 정의 위에 @데코레이터이름으로 적용합니다.

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

결과:

함수 실행 전
Hello!
함수 실행 후

설명: say_hello() 함수를 호출하면 @my_decorator 데코레이터가 적용되어 wrapper 함수가 실행됩니다. 따라서 say_hello() 함수는 "함수 실행 전", "Hello!", "함수 실행 후" 순으로 출력됩니다.


3. 인자를 받는 함수에 데코레이터 적용

인자를 받는 함수에 데코레이터를 적용하려면 *args와 **kwargs를 사용하여 모든 인자를 전달받도록 합니다.

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("함수 실행 전")
        result = func(*args, **kwargs)
        print("함수 실행 후")
        return result
    return wrapper

@my_decorator
def add(a, b):
    return a + b

print(add(3, 5))

결과:

함수 실행 전
함수 실행 후
8

설명: add(3, 5) 호출 시, @my_decorator가 add 함수를 래핑하여 "함수 실행 전", "함수 실행 후"를 출력하고, 결과로 8을 반환합니다.


4. 여러 데코레이터 중첩 적용

여러 데코레이터를 중첩해서 적용할 수 있습니다. 데코레이터는 위에서 아래 순서로 적용됩니다.

def bold(func):
    def wrapper(*args, **kwargs):
        return "<b>" + func(*args, **kwargs) + "</b>"
    return wrapper

def italic(func):
    def wrapper(*args, **kwargs):
        return "<i>" + func(*args, **kwargs) + "</i>"
    return wrapper

@bold
@italic
def text():
    return "Hello, World!"

print(text())

결과:

<b><i>Hello, World!</i></b>

설명: @italic가 먼저 적용되어 <i>...</i>로 감싸지고, 그 다음 @bold가 적용되어 최종 출력이 <b><i>Hello, World!</i></b>로 반환됩니다.


5. 함수 실행 시간 측정 데코레이터 예제

데코레이터는 함수의 실행 시간을 측정하는 데 유용하게 사용될 수 있습니다.

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"실행 시간: {end_time - start_time:.4f}초")
        return result
    return wrapper

@timer
def slow_function():
    time.sleep(2)
    print("작업 완료")

slow_function()

결과:

작업 완료
실행 시간: 2.0003초

설명: @timer 데코레이터는 함수 실행 전후의 시간을 측정하고, slow_function()의 실행 시간을 출력합니다.


6. 접근 제어 데코레이터 (예: 로그인 필요)

특정 기능을 수행하기 전 사용자 인증이 필요할 때 데코레이터를 활용하여 접근 제어를 할 수 있습니다.

def requires_login(func):
    def wrapper(user, *args, **kwargs):
        if not user.get("is_logged_in"):
            print("로그인이 필요합니다.")
            return
        return func(user, *args, **kwargs)
    return wrapper

@requires_login
def view_profile(user):
    print(f"{user['name']}님의 프로필을 보여줍니다.")

# 예제 사용자
user = {"name": "Alice", "is_logged_in": False}
view_profile(user)  # 결과: 로그인이 필요합니다.

user["is_logged_in"] = True
view_profile(user)  # 결과: Alice님의 프로필을 보여줍니다.

설명: @requires_login 데코레이터는 user 딕셔너리의 is_logged_in 값이 True인지 확인하여, 로그인 여부에 따라 함수 실행을 제어합니다.


7. 클래스 메서드에 데코레이터 적용

데코레이터는 클래스 메서드에도 사용할 수 있습니다. 클래스 메서드나 정적 메서드에 데코레이터를 적용하려면 @classmethod나 @staticmethod와 함께 사용할 수 있습니다.

def log_method_call(func):
    def wrapper(*args, **kwargs):
        print(f"{func.__name__} 메서드가 호출되었습니다.")
        return func(*args, **kwargs)
    return wrapper

class MyClass:
    @log_method_call
    def instance_method(self):
        print("인스턴스 메서드 실행")

    @classmethod
    @log_method_call
    def class_method(cls):
        print("클래스 메서드 실행")

my_instance = MyClass()
my_instance.instance_method()
MyClass.class_method()

결과:

instance_method 메서드가 호출되었습니다.
인스턴스 메서드 실행
class_method 메서드가 호출되었습니다.
클래스 메서드 실행

설명: @log_method_call 데코레이터가 instance_method와 class_method 호출 시마다 실행되어, 메서드 호출을 로깅합니다.


8. 인자를 받는 데코레이터

데코레이터에 인자를 전달하려면, 데코레이터를 한 번 더 감싸는 함수를 사용합니다.

def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                func(*args, **kwargs)
        return wrapper
    return decorator

@repeat(3)
def greet():
    print("Hello!")

greet()

결과:

Hello!
Hello!
Hello!

설명: @repeat(3) 데코레이터는 greet() 함수를 세 번 반복해서 호출하도록 만듭니다.

 

데코레이터는 코드의 재사용성과 유지보수성을 높여주며, 프로그램에 유연한 기능을 추가하는 데 매우 유용합니다.

반응형
Posted by 녹두장군1
,