파이썬/파이썬(python) 중급

데코레이터, 일급 객체, 중첩함수, 데코레이터 함수 만드는 방법

Olivia-BlackCherry 2022. 11. 2. 16:51

데코레이터란?

각 함수에 기능을 따로 추가하고 싶을 때 데코레이터를 사용한다. 

다시 말해 이미 있는 함수에 다른 기능을 더하는 함수이다. 

데코레이터 개념을 설명하기 앞서 아래의 두 가지 파이썬 문법을 복습해보자. 

 

1. 파이썬 함수는 일급 객체(First-class object)

일급 객체라는 뜻은 함수를 인자로 전달할 수 있는 것이다.

def divide(n1, n2):
    return n1/n2

def calculate(cal_func, n1, n2):
    return cal_func(n1,n2)

 

 

2. 중첩함수의 다양한 출력 방식
def outer_func():
    print("outer")
    def nested_func():
        print("inner")
    return nested_func

outer_func()

>>outer

 

def outer_func():
    print("outer")
    def nested_func():
        print("inner")
    return nested_func()

outer_func()

>>outer
inner

 

def outer_func():
    print("outer")
    def nested_func():
        print("inner")
    return nested_func

inner_func = outer_func()
inner_func()

>>outer
inner

 

 

데코레이터 예시 

아래의 함수가 실행되기 전에 2초 간의 공백을 두려고 한다. 

def say_hello():
    print("안녕")

def say_bye():
    print("다시 만나")

def say_welcome():
    print("환영해")

 

원래라면, time모듈을 불러와서, 각 함수에 time.sleep(2)를 추가해줘야 한다.

import time

def say_hello():
    time.sleep(2)
    print("안녕")

def say_bye():
    time.sleep(2)
    print("다시 만나")

def say_welcome():
    time.sleep(2)
    print("환영해")

 

데코레이터 함수를 이용하면 반복을 줄이고 효율적인 코드를 만들 수 있다.

다른 함수를 감싸는 함수인 데코레이터 함수를 만들어,

기존 함수에 기능을 더하거나 변형시켜 보자.

 

우선 새로운 함수를 만든다. 어떤 함수를 인자로 넣었을 때, 

그 함수는 2초 간의 공백을 두고 실행된다.

def delay_decorator(func):
    def wrapper_func():
        time.sleep(2)
        func()

    return wrapper_func

 

 

기존의 방식대로라면,

say_hello 함수에 위의 기능을 추가해주려면 아래와 같이 코드를 작성하면 된다.

decorated_func = delay_decorator(say_hello)
decorated_func()

 

이번에는 데코레이터 @를 이용해보자.

이 함수의 기능을 추가해주고 싶은 함수 앞에 아래와 같이 붙여준다. 

@delay_decorator
def say_hello():
    print("안녕")

 

원하는 곳에만 붙여주면 된다.

훨씬 간결하고, 빠르다.

@delay_decorator
def say_hello():
    print("안녕")

def say_bye():
    print("다시 만나")

@delay_decorator
def say_welcome():
    print("환영해")

say_hello()
say_bye()
say_welcome()

 

 

<예제>

import time
current_time = time.time()

def speed_calc_decorator(func):
  def wrapper_func():
    func()
    now_time = time.time()
    print(f"그 다음 시간{now_time}")
    diff_time = now_time- current_time
    print(f"시간 차이{diff_time}")
    func()
  return wrapper_func

@speed_calc_decorator
def fast_function():
    for i in range(10):
        i * i


@speed_calc_decorator
def slow_function():
    for i in range(1000000):
        i * i

fast_function()
slow_function()

# a =speed_calc_decorator(slow_function)
# print(a)

>>그 다음 시간1667377370.0591247
시간 차이6.67572021484375e-06
그 다음 시간1667377387.2767382
시간 차이17.217620134353638