Python - decorator

JUGNMIN LEE·2021년 5월 29일
0

Python

목록 보기
1/1
post-thumbnail

decorator ?

데코레이터는 말 그대로 장식자라고도 부르며 파이썬에서는 반드시 알고 있어야 하는 기능이다

데코레이터는 왜 사용할까 ?

데코레이터가 없다고 해서 나라가 망하냐 ? 파이썬을 못하냐 ? 아니다

다만 데코레이터가 없다면 코드의 복잡성은 크게 올라간다
즉 우리가 쉽게 코딩을 하기 위해서 사용하는 것이라고 생각하면 된다.

데코레이터는? = 함수다

또한 데코레이터는 클로저라는 개념과 연결이 되어 있다
이는 다른 언어에서도 클로저라는 개념이 있는 것과 같으며 어떠한 정보를 기반으로
연산을 실행하고 싶지만 기반이 되는 정보는 접근을 제한하여 노출이 되거나
수정이 되지 못하게 하고 싶을때 사용한다.

주로 factory 패턴을 구현할때 사용되는 것이다.

factory 패턴 : 무언가를 생성해내는 말 그대로 공장의 기능을 가진 패턴
(함수나 오브젝트를 생성해내는데 사용)

이런 설정값을 노출하지 않아 수정이 불가능하게 하면서 해당 설정값을 기반으로한
연산을 하는 기능을 가진 함수를 만들때 클로저 라는 개념이 들어가며

데코레이터는 이런 클로저라는 개념을 한단계 더 나아가 사용하는 기능이다.

데코레이터 사용 1

데코레이터를 코드로 구현해보자.

def trace(func):                             # 호출할 함수를 매개변수로 받음
  def wrapper():                           # 호출할 함수를 감싸는 함수
      print(func.__name__, '함수 시작')    # __name__으로 함수 이름 출력
      func()                               # 매개변수로 받은 함수를 호출
      print(func.__name__, '함수 끝')
  return wrapper                           # wrapper 함수 반환
 
def hello():
  print('hello')
 
def world():
  print('world')
 
trace_hello = trace(hello)    # 데코레이터에 호출할 함수를 넣음
trace_hello()                 # 반환된 함수를 호출
trace_world = trace(world)    # 데코레이터에 호출할 함수를 넣음
trace_world()                 # 반환된 함수를 호출

위 코드와 같이 trace라는 데코레이터 함수는 호출할 함수를 매개변수로 받게 된다.
그리고 trace 함수 안에서는 호출할 함수를 감싸는 wrapper라는 함수를 만들고 return을 사용하여 wrapper 함수 자체를 반환한다.

즉 아까 위에서 설명했던 클로저의 개념이 이렇게 사용된다.
함수 안에서 함수를 만들고 그 함수를 반환한다!!

데코레이터 사용 2

그렇다면 이제 @를 사용하여 좀 더 간편하게 데코레이터를 사용해보자.

형식은 아래와 같고

@decorator
def func():
  print('하이 데코ㅎㅎ')

아까 위에서 설정한 trace라는 데코레이터 함수를 만든 것을 @decorator 라는 형식으로 다시 지정해본다.

def trace(func):                             # 호출할 함수를 매개변수로 받음
  def wrapper():
      print(func.__name__, '함수 시작')    # __name__으로 함수 이름 출력
      func()                               # 매개변수로 받은 함수를 호출
      print(func.__name__, '함수 끝')
  return wrapper                           # wrapper 함수 반환
 
@trace    # @데코레이터
def hello():
  print('hello')
 
@trace    # @데코레이터
def world():
  print('world')
 
hello()    # 함수를 그대로 호출
world()    # 함수를 그대로 호출

이렇게 @trace라는 데코레이터 기능을 이용해 기존 함수를 수정하지 않으면서
추가 기능을 구현할 수 있다.

데코레이터를 여러개 지정하면 순서는?

함수에는 데코레이터를 여러개 지정할 수 있다
위에서는 @trace로 한개만 지정하였지만 아래와 같은 코드 처럼 여러개도 지정할 수 있으며 그에 따른 순서는 실행 결과 값과 같으며 그러한 이유는 아래의 부가 설명과 같다.

def decorator1(func):
  def wrapper():
      print('decorator1')
      func()
  return wrapper
 
def decorator2(func):
  def wrapper():
      print('decorator2')
      func()
  return wrapper
 
# 데코레이터를 여러 개 지정
@decorator1
@decorator2
def hello():
  print('hello')
 
hello()

# 실행 결과
decorator1
decorator2
hello

# 실행 결과의 이유 부가 설명 코드
decorated_hello = decorator1(decorator2(hello))
decorated_hello()
profile
Frontend Developer

0개의 댓글