데코레이터 (Decorator)

2021. 11. 9. 17:08·[Language] - Python

개요


데코레이터를 이해하기 이전에 함수형 프로그래밍에 대한 (함수를 일급시민으로 취급하는) 개념을 먼저 살피고 오면 좋다. 데코레이터는 사전적으로 장식자라는 의미를 가지고 있으며, 장식의 대상이 되는 함수를 데코레이터 함수의 인자로 전달하여 내부적으로 실행방식을 래핑(Wrap)한다.

 

데코레이터 사용법은 대상이 되는 함수 위에 @데코레이터명 을 쓰면 된다. 예를 들면, @staticmethod, @classmethod, @property 등 다양한 데코레이터들이 있고, 사용자가 임의로 데코레이터를 정의할 수도 있다.

 


 

 

클로저 (Closure)


def closure(msg):
    def wrapper():
        print(msg)
    return wrapper

func = closure("Hello, World!")
func() # Hello, World!
  • 데코레이터를 이해하기 이전에 클로저부터 살펴보자. 클로저는 특정 함수가 정의되었을 때, 해당 함수와 렉시컬 환경(Lexical environment)와의 조합으로 정의된다.
    • 쉽게 말해, 외부 함수(Outer Function) 스코프 내에 정의된 내부 함수(Inner Function)가 외부 함수의 상태를 참조할 수 있는 것을 의미한다. 여기서 외부 함수 스코프가 Lexical environment에 대응된다.
    • 위 예시에서는, 외부 함수는 closure 함수이고, 내부 함수는 wrapper 함수다. wrapper 함수에서 closure 함수에 정의된 msg 변수를 참조할 수 있다.
    • Lexical은 "단어" 혹은 "어휘"의 의미를 가지고 있고, Lexicon은 사전(단어 혹은 어휘를 모아둔 책)을 의미한다. Lexical Scope의 의미는 코드가 작성된 위치에 따라 결정되는 범위를 의미한다. 즉, 함수 혹은 변수가 호출된 위치가 아니라 정의된 위치가 중요한 포인트다. Lexical Scope는 다른 의미로 Static Scope라고도 불린다.
x=10

foo() {
  echo $x
}

bar() {
  local x=20
  foo
}

bar # 출력: 20 (Bash는 동적 스코프)
  • 위 예시는 Dynamic Scope에 대한 예시다. 정의된 스코프 위치가 아닌 호출하는 시점에서 가장 근접한 스코프로부터 참조하는 방식이다.

 


 

데코레이터 정의 예제


def say_hi():
    print("i'm function")
    print('hi')


def say_hello():
    print("i'm function")
    print('hello')


def say_bye():
    print("i'm function")
    print('bye')
  • 예를 들어, 위와 같이 "i'm funciton" 이라는 문자열을 출력하는 중복된 코드가 존재한다. 만약 중복되는 패턴이 무수히 늘어난다고 극단적으로 생각해보자. 이러한 경우에 대해 데코레이터 패턴을 적용하여 리팩터링할 수 있다.

 

# 데코레이터 함수 정의
def example_deco(func):
    def wrapper(*args, **kwargs):
        print("i'm function")
        func()
    # 인자로 전달받은 함수 func를 래핑하여 반환
    return wrapper


@example_deco
def say_hello():
    print('hello')


@example_deco
def say_bye():
    print('bye')
    
say_hello() # Output: i'm function \n hello
say_bye() # Output: i'm function \n bye
  • 데코레이터 함수는 외부 함수와 내부 함수를 정의해야 한다. 위 예시에서는 example_deco 함수를 정의했다.
  • 내부 함수인 wrapper에서는 클로저의 특성으로 외부 함수에서 정의된 func를 호출할 수 있다.
  • example_deco 함수의 반환값은 func 함수를 추가 동작을 정의하여 래핑한 wrapper 함수의 레퍼런스를 반환한다.

 

def example_deco(msg):
    def wrapper(func):
        def inner(*args, **kwargs):
            print(f"i'm {msg}")
            func(*args, **kwargs)
        return inner
    return wrapper


@example_deco(msg="decorated")
def say_what(something):
    print(something)
    
say_what(something="hello world")  # Output: i'm decorated \n hello world
  • 위 예시는 데코레이터 애노테이션을 적용하는 과정중에 인자를 전달하는 예시다.
  • 좀더 복잡해졌지만, 사실상 wrapper와 inner는 이전에 예시로 본 example_deco와 wrapper에 대응된다. (Outer Function, Inner Function)
  • 새롭게 추가된건 가장 최상단의 def example_deco(msg) 라인인데, 이는 데코레이터를 호출할 때, 전달할 파라미터를 정의하기 위한 것이다.

'[Language] - Python' 카테고리의 다른 글

Python 객체의 생명 주기와 메모리  (0) 2021.08.02
[Tip] 딕셔너리 Fancy하게 다루기  (0) 2021.05.28
[Tip] win32com 모듈을 사용한 엑셀 제어  (0) 2021.04.20
제너레이터 (Generator)  (0) 2021.04.14
함수형 프로그래밍  (0) 2021.03.25
'[Language] - Python' 카테고리의 다른 글
  • Python 객체의 생명 주기와 메모리
  • [Tip] 딕셔너리 Fancy하게 다루기
  • [Tip] win32com 모듈을 사용한 엑셀 제어
  • 제너레이터 (Generator)
Bebsae
Bebsae
  • Bebsae
    뱁새zip
    Bebsae
  • 전체
    오늘
    어제
    • 분류 전체보기 (108)
      • [DevOps] - Kubernetes (5)
      • [DevOps] - AWS (1)
      • [AI] - Machine Learning (19)
      • [AI] - Neural Network (7)
      • [CS] - Network (2)
      • [CS] - Data Structure (3)
      • [CS] - Design Pattern (6)
      • [Language] - Python (15)
      • [Library] - Numpy (7)
        • Quick Start (5)
        • API (2)
      • [Framework] - Django (3)
      • [Framework] - QGIS (6)
      • [Framework] - PyQT (4)
      • [Mathematics] - Linear Alge.. (14)
      • [Mathematics] - Statistical (2)
      • [ETC] - Python (3)
      • [ETC] - C++ (1)
      • [ETC] - Linux (1)
      • 논문 (5)
      • 회고록 (3)
      • 생산성 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
  • 공지사항

  • 인기 글

  • 태그

    파이썬
    QGIS
    algebra
    교차검증
    분해
    Linear
    Convolution
    Machine
    신경망
    Python
    머신러닝
    선형대수
    RNN
    DEEPLEARNING
    linearalgebra
    MachineLearning
    numpy
    Learning
    디자인패턴
    decomposition
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Bebsae
데코레이터 (Decorator)
상단으로

티스토리툴바