카테고리 없음

스파르타 AI-8기 TIL(1/29)-개인 공부

kimjunki-8 2025. 1. 29. 22:35
데코레이터 (Decorators)
데코레이터는 함수를 감싸는 함수라고 생각하면 됩니다. 즉, 어떤 함수의 동작을 변경하거나 확장하는 역할을 합니다. @ 문법을 사용하여 함수 또는 클래스에 적용할 수 있습니다.
def my_decorator(func):  # hello()가 func으로 전달됨
    def wrapper():
        print("함수 실행 전")
        func()  # hello() 실행
        print("함수 실행 후")
    return wrapper  # wrapper 함수 반환

@my_decorator  # hello()를 my_decorator(hello)로 변환
def hello():
    print("Hello, world!")

hello()

출력:
함수 실행 전
Hello, world!
함수 실행 후

@my_decorator가 hello()를 감쌉니다.
즉, 아래 코드와 동일한 효과가 발생합니다.

hello = my_decorator(hello)

이제 hello()를 실행하면 실제로는 wrapper()가 실행됩니다.

hello()를 호출하면 wrapper()가 실행됩니다.
"함수 실행 전" 출력
func() 실행 → 즉, 원래 hello() 실행 (print("Hello, world!"))
"함수 실행 후" 출력

2개도 가능

def deco1(func):
    def wrapper():
        print("deco1 실행")
        func()
    return wrapper

def deco2(func):
    def wrapper():
        print("deco2 실행")
        func()
    return wrapper

@deco1
@deco2
def greet():
    print("안녕하세요!")

greet()

출력:
deco1 실행
deco2 실행
안녕하세요!​


함수에 인자가 있는 경우

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, 4))​

출력:
함수 실행 전
함수 실행 후
7


참고로 오버라잇도 가능합니다
보통 클래스에서 메서드를 오버라이딩

def override_decorator(func):  # (1) original_function이 func로 전달됨
    def wrapper(*args, **kwargs):  # (2) wrapper가 원래 함수 대신 실행됨
        print("새로운 기능으로 오버라이딩!")  # (3) 새로운 기능만 실행
        return "이전 기능은 사라졌습니다."  # (4) 원래 함수는 실행되지 않음
    return wrapper  # (5) wrapper를 반환하여 원래 함수를 대체

@override_decorator  # (6) original_function = override_decorator(original_function)
def original_function():
    print("원래 기능입니다.")

print(original_function())  


출력:
새로운 기능으로 오버라이딩!
이전 기능은 사라졌습니다.

이게 어떻게 오버라잇인가?
저 original_function이 fun으로 들어가게 되는데, 최종적으로 저 func을 안 쓰게 됩니다. 즉, 받기만하고 실제로 작동하게 하는 함수는 wrappe가 되게 되는것입니다.
포인트: func()을 실행하지 않으므로 기존 기능이 완전히 사라지고 새로운 기능만 실행됨.



정리:
@override_decorator가 original_function을 func으로 전달받음.
override_decorator(original_function) 실행됨.
override_decorator()는 내부적으로 wrapper 함수를 반환.
즉, original_function이 이제 wrapper 함수로 교체됨.
original_function()을 실행하면 실제로는 wrapper()가 실행됨.
wrapper() 내부에서 func()을 호출하지 않았으므로 원래 기능은 실행되지 않음.
결과적으로 "새로운 기능으로 오버라이딩!"만 출력됨.

그리고 만약에 여기서 func를 쓰게되면 부분적 오버라잇이 되게 됩니다.

def modify_decorator(func):
    def wrapper(*args, **kwargs):
        print("기능이 확장되었습니다!")
        result = func(*args, **kwargs)  # 원래 함수 실행
        return result + " - 추가된 내용"
    return wrapper

@modify_decorator
def greet():
    return "안녕하세요!"

print(greet())

출력:
기능이 확장되었습니다!
안녕하세요! - 추가된 내용