수학과의 좌충우돌 프로그래밍

[python] 장식자, 데코레이터(decorator) 를 알아보자 본문

프로그래밍 언어/Python

[python] 장식자, 데코레이터(decorator) 를 알아보자

ssung.k 2019. 8. 8. 03:11

python 으로 작성된 다른 코드들을 보다보면 아래와 같이 어느 함수 위에 @ 가 있는 걸 볼 수 있습니다. 이 @ 는 무엇을 나타내고 어떤 역할을 하지는 알아보도록 합시다.

@decorator
def function1():
  print("ssungkang")

 

decorator 란?

제목에서 알 수 있듯이 이것이 바로 decorator 입니다. 사실 데코레이터가 없다고 해서 구현을 못하는 일이 생기는 건 아니지만 코드가 복잡해집니다. 즉 사용자가 편리해지기 위한 것 이라고 생각하면 됩니다. 지금부터 decorator 에 대해서 알아보도록 하겠습니다.

decorator 는 사실 하나의 함수입니다. 어떤 함수냐면 다른 함수를 감싸고 있는 함수죠. 아래 예시를 봐보도록 합시다.

def decorator(func):
  def deco_func():
    print("tistory")
    func()
  return deco_func
    
def function1():
  print("ssungkang")
  

function1 = decorator(function1)
function1()
# tistory
# ssungkang

기존의 function1 함수는 단순히 ssungkang 만을 출력하는 함수입니다. 이 함수를 decorator 라는 함수에 씌어준 결과, 기존의 출력 이외에 tistory 라는 출력도 포함합니다. 코드가 어렵지는 않으나 함수를 매개변수로 받고 그 안에 함수를 또 만들고 그 함수를 반환하게 됩니다. 생각보다 이러한 작업은 범용적으로 많이 쓰이며 쓰지 않는 라이브러리를 찾기가 힘들 정도입니다. 그래서 이를 간결하게 하기 위해서 파이썬은 decorator 를 지원해줍니다.

def decorator(func):
  def deco_func():
    print("tistory")
    func()
  return deco_func

@decorator
def function1():
  print("ssungkang")

function1()	
# tistory
# ssungkang

다음과 같이 @ + 감싸주는 함수이름을 함수 위에 적어줄 경우, 위와 같은 효과를 가져 올 수 있습니다.

복잡한 코드가 여러 함수에 중복적으로 들어가야할 경우 decorator 를 통해서 단순화 해 줄 수 있습니다.

 

인자를 가지는 decorator

이번에는 위의 코드를 조금 응용해서 각 함수마다 tistory 를 출력하는 횟수가 달라야 한다고 가정해보겠습니다. 그러면 장식자는 인자를 받아야 할 것입니다.

우선 장식자를 사용하지 않은 코드입니다.

def decorator(n):
    def outer(func):
        def deco_func():
            for i in range(n):
                print("tistory")
            func()
        return deco_func
    return outer

def function1():
    print("ssungkang")

decorator_3 = decorator(3)
function1 = decorator_3(function1)

function1()	
# tistory
# tistory
# tistory
# ssungkang

기존 decorator 가 하던 함수를 받는 역할을 outer 가 대신 해주고 이번에는 decorator 는 n 값을 받아서 그 n 값 만큼 출력을 반복하는 새로운 함수를 반환하게 됩니다. 이를 장식자로 사용하는 것도 똑같은 원리로 적용해주면 됩니다.

def decorator(n):
    def outer(func):
        def deco_func():
            for i in range(n):
                print("tistory")
            func()
        return deco_func
    return outer

@decorator(3)
def function1():
    print("ssungkang")


function1()	
# tistory
# tistory
# tistory
# ssungkang

 

Comments