Daily Log

헷갈리는 python 데코레이터

jaehwi0823 2022. 1. 8. 14:14

파이썬 기본서에서 "데코레이터는 함수를 감싸고 반복되는 추가 기능을 쉽게 넣어준다" 까지 배우고 사실 한 번도 직접 만들어서 써 본 적이 없다.

 

마침 새롭게 짜는 코드의 함수들에 반복되는 로직이 있어 데코레이터를 써 볼 기회가 생겼다. 

그런데 분명 개념은 쉬웠는데 막상 쓰려니 왜이리 헷갈리는지..

남이 만든 것을 쓸 때는 편했는데....

 

한참을 헤매고 나름의 정리를 해봤다.

 

1. 파라미터 없는 데코레이터

def deco(func):
    def wrapper():
        print("inner wrapper")
        func()
    return wrapper

@deco
def myfunc():
    print("out function")

myfunc()

# >> inner wrapper
# >> out function
  • 위의 코드는 그래도 간단한 편이다
  • myfunc 함수는 wrapper 함수로 변신하고, wrapper 함수에서 myfunc 함수의 내용을 사용한다
  • 즉, deco 함수에 myfunc가 인자로 들어가는 것이다!
  • 여기서 @deco 부분에 괄호가 없는 것이 포인트

파라미터 없는 데코레이터 참조도

 

2. 파라미터가 있는 데코레이터

def deco(*args, **kwargs):
    def inner(func):
        def wrapper(msg):
            print("inner wrapper")
            print(args)
            func(msg)
        return wrapper
    return inner

@deco("decorator Args")
def myfunc(msg):
    print("out function")
    print(msg)

myfunc("param msg")

# >> inner wrapper
# >> ('decorator Args',)
# >> out function
# >> param msg
  • 파라미터가 들어갈 때부터 갑자기 헷갈리기 시작한다
  • 데코레이터는 다음 def 대상을 인자로 인식한다
  • 그러므로 "decorator Args"는 deco 함수의 *args로 들어가고, myfunc는 inner 함수의 func가 된다
  • 마지막으로 inner가 wrapper를 반환하므로 myfunc는 wrapper를 참조하게된다

파라미터가 있는 데코레이터

  • 위의 코드는 바로 다음 코드와 동일하다
  • "이제 눈 감고도 데코레이터를 쓸 수 있다"는 아니더라도 헷갈리던 내용이 조금은 정리된 것 같다
def deco(*args, **kwargs):
    def inner(func):
        def wrapper(msg):
            print("inner wrapper")
            print(args)
            func(msg)
        return wrapper
    return inner

def myfunc(msg):
    print("out function")
    print(msg)

deco("decorator Args")(myfunc)("param msg")