TIL DAY 7 || Python Decorator

tk_kim·2021년 2월 21일
0

TIL

목록 보기
9/55
post-thumbnail

Decorator

  • Decorator 는 chain of functions 즉, 여러개의 함수가 자동으로 연속적으로 호출되게하는 기능을 한다.

  • Decorator로 장식할 수 있는 함수는 중첩 함수(nested function)을 리턴하는 함수만 decorator 함수로 사용될 수 있다.

다음은 데코레이터로 둘러쌓인 함수가 특정 조건을 만족할 때만 수행되게 하는 예제이다.

# n번 (진행되는 순서) / n번 (return 값이 나오는 순서)

def is_valid_user(func): # 2번
    is_valid = True

    def wrapper(): # 4번
        if is_valid:
            return func()  # 5번 / 2번 
            		   # return 이 아니라 func() 만 호출하면
            		   # say_hi() 의 return 값은 None 이 되어버린다. 
        else:
            return
    return wrapper # 3번 / 3번


@is_valid_user
def say_hi(): # 6번
    return 'hi' # 7번 / 1번


hello = say_hi() # 1번 / 4번
print(hello) # 'hi'
  • decorator 로 둘러쌓여있는 say_hi() 함수를 호출하면 파이썬은 이를 is_valid_user(say_hi) 로 해석하여 호출해준다.

  • is_valid_user(func)의 인자로 say_hi() 함수 자체가 들어간다.

  • is_valid_user() 는 중첩함수인 wrapper를 리턴한다.

  • wrapper() 함수 안에서 조건문 비교를 한다.

  • wrapper 함수를 호출하기 전 is_valid 의 값은 True 였으므로 첫 번째 is_valid: 블럭으로 들어간다.

  • func() 을 return 한다.

  • fucn() 의 return 값 'hi'wrapper() 의 return 값이며, 최종적으로 데코레이터로 둘러쌓인say_hi() 의 return 값이다.

  • 따라서 변수 hello 의 값이 'hi' 가 된다.

하지만 이 때 wrapper() 함수 내부에서 func() 을 return 하지않고 그저 호출만 한다면,

  • wrapper() 함수의 return 값은 None 이 되므로 is_valid_user() 함수의 return 값 또한 None 이 되기 때문에 최종적으로 데코레이터로 둘러쌓인 say_hi() 의 return 값은 None이 된다.
  • 따라서 변수 hello 의 값이 None 이 된다.

정리

이렇듯 decorator 는 특정 조건 하에서만 함수가 실행되야만 할 때 편하게 사용하기 위해 작성하는 함수이다.

또한 하나의 함수에 여러개의 decorator 를 중첩해서 사용할 수 있다.

다음 코드는 tornado 웹 프레임워크를 사용해 작성한 코드의 일부이며, 주식코드를 async 하게 가져오는 내용이다.

물론 이미 만들어져있는 데코레이터를 가져다 쓴 것이지만, 실용성은 매우 높았다.

예를들어 @tornado.web.authenticated 데코레이터는 유저가 로그인 되어있는지 체크한 뒤 로그인 되어있을 때만 특정 함수를 실행한다.

또한 @run_on_executor 데코레이터는 sync 한 특정 함수를 설정했던 thread pool executor 위에서 async 하게 실행해준다.

이렇게 데코레이터를 사용해본 적은 있지만 사실 직접 데코레이터를 만들어보고 자세히 공부해보는 것은 처음이다. 앞으로 직접 유용한 데코레이터를 직접 만들어 볼 수 있을 것 같다.

profile
Backend Developer

0개의 댓글