Python - Decorator

Enjoywater·2020년 8월 23일
0

TIL

목록 보기
8/33
post-thumbnail
먼저 알아야 할 것 - First-class citizen / Closure

Decorator

Decorator란

  • Closure처럼 중첩함수를 return하는 함수이다.
  • 다른 함수에 적용해서, 적용된 함수가 실행되기 전에 무조건 먼저 실행이 된다.
  • 즉, 적용된 특정 함수가 실행되기 전에 강제적으로 다른 함수가 실행이 된 후에 실행되도록 하는 강제성을 가지는 기능이다.
  • 특정 함수 위에 '@함수명'의 형태로 사용된다.
def decorator_func(func):
    def wrapper():
        print("decorator_func 작동")
        print(func())
    return wrapper

@decorator_func    
def any_func():
     return "any_func 작동"
     
any_func()

함수를 parameter로 받고, wrapper라는 내부함수를 가지고 return하는 decorator_func 함수가 있다.
wrapper함수는 decorator_func의 parameter함수를 실행 후 출력한다.

any_func함수 위에, @decorator_func가 장식처럼 쓰여지고 있다.
때문에 장식자 = decorator라는 이름으로 불린다.

해당 코드를 실행하면,

decorator_func 작동   
any_func 작동 

으로 결과값이 나온다.
any_func함수가 실행이 되기전에 decorator_func가 먼저 실행이 된 것을 알 수 있다.

any_func를 호출 할 때, 파이썬이 자동적으로

deco_result = decorator_func(any_func)
deco_result()

로 변환해서 호출한다.

Decorator + parameter

위 코드는 고정된 값을 호출하는 함수로 되어있다.
하지만 @함수명(param)의 형식으로 parameter를 받는 형식으로 작성할 수 있다.

def join_name(name):
    def first(func):
        def second():
            print(func() + name + "!")
        return second
    return first

@join_name("Water")
def welcome():
    return "Welcome, "
    
welcome()

# 결과값 -> Welcome Water!

앞서 보았던 예시와는 다르게 3가지 함수가 중첩되어 있다.

  • name이라는 문자열을 parameter를 받고 first함수를 return하는 join_name함수,
  • func라는 함수를 parameter로 받고 second함수를 return하는 first함수,
  • 그리고 위 parameter들을 합쳐서 출력하는 second함수로 이루어져 있다.

하나하나 살펴보면 앞서 본 예시와 크게 차이는 없다.
하지만 함수를 한번 더 씌워주면서 아래와 같이 유동적인 결과를 나타낼 수 있다.

# @join_name( 위 코드에서 여기만 변경한 후 출력 )

@join_name("Enjoywater")
...
# 결과값 -> Welcome Enjoywater!

@join_name("Lee")
...
# 결과값 -> Welcome Lee!

이와같은 코드는 파이썬이 실행 할 때,

pre_result = join_name("Water")
result = pre_result(welcome)
result()

로 변환해서 호출하게 된다.

또한, 결과를 호출하는 welcome함수에 parameter를 받아서 더 편리하게도 사용할 수 있다.

def join_name(greet):
    def first(func):
        def second(name):
            print(greet + func(name) + "!")
        return second
    return first

@join_name("Welcome ")
def welcome(name):
    return name
    
welcome("Water")

# 결과값 -> Welcome Water!

이렇게 코드가 변경되면,
!를 제외한 나머지 인사말과 이름을 변경하며 출력할 수 있게된다.

profile
블로그 이전 👉🏻 enjoywater.tistory.com

0개의 댓글