데코레이터 (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()) 출력: 기능이 확장되었습니다! 안녕하세요! - 추가된 내용