본문 바로가기
프로그래밍/Python

파이썬(Python) 데코레이터(Decorator)에 대해서 알아보자 (feat. @)

by 부자 꽁냥이 2022. 9. 19.

파이썬(Python)에서는 데코레이터(Decorator)라는 것이 있다. 뭔가를 꾸미는 장식가라는 의미의 데코레이터(Decorator)라는 단어에서 알 수 있듯이 데코레이터(Decorator)는 다른 함수를 꾸며주는 함수로써 다른 함수의 추가 기능을 부여할 때 사용된다.

 

이번 포스팅에서는 데코레이터의 사용법을 알아보려고 한다.


   데코레이터(Decorator)로 함수를 꾸며보자

먼저 꾸밀 함수를 정의해보자. 아래 코드에서 정의된 함수는 'Sleeping'이라는 문자열을 출력하고 3초간 잠을 자는(아무것도 안 하는) 함수이다.

 

import time

def f():
    '''
    Just Function
    '''
    print('Sleeping')
    time.sleep(3)

1) 데코레이터(Decorator) 만들기

이제 위 함수를 꾸며보자. 위 함수의 실행시간을 출력시키는 기능을 꾸며볼 것이다(기능을 추가한다는 뜻이다). 먼저 아래와 같이 데커레이터 run_time를 정의하자.

 

def run_time(func):
    def wrapper():
        start_time = time.time() ## 함수 시작 시간 저장
        print(f'{func.__name__} 실행 시작시간 : {start_time}') ## 함수 이름, 실행 시작 시간 출력
        func() ## 함수 실행
        end_time = time.time() ## 함수 종료 시간 저장
        print(f'{func.__name__} 실행 완료시간 : {end_time}') ## 함수 이름, 종료 시간 출력
        print(f'총 실행시간 {end_time-start_time}') ## 실행시간 출력
    return wrapper

 

이제 데코레이터를 실행해보자. 데코레이터 (첫 번째) 인자에 꾸며주고 싶은 함수를 넣고 이를 실행하면 된다. 

 

run_time_f = run_time(f)
run_time_f()

 


2) @를 이용하여 데코레이터 사용하기

파이썬에서는 데코레이터(Decorator)를 사용할 수 있는 좀 더 멋진 방법을 제공한다. 바로 '@'을 사용하는 것이다. 사용법은 꾸며질 함수 정의하는 부분 바로 위에다가 '@데코레이터' 형식으로 써주면 된다.

 

아래 코드는 앞에서 살펴본 run_time을 직접 호출하는 방식과 동일하게 작동한다.

 

@run_time
def f():
    '''
    Just Function
    '''
    print('Sleeping')
    time.sleep(3)
    
f() ## 데코레이터가 추가된 함수 실행

 

 

참고로 위에서 함수 f의 실행 과정은 다음과 같다.

파이썬(Python) 데코레이터(Decorator)

만약 함수에 인자가 있다면 wrapper에 정의하면 된다.

 

def run_time(func):
    def wrapper(string):
        start_time = time.time() ## 함수 시작 시간 저장
        print(f'{func.__name__} 실행 시작시간 : {start_time}') ## 함수 이름, 실행 시작 시간 출력
        func(string) ## 함수 실행
        end_time = time.time() ## 함수 종료 시간 저장
        print(f'{func.__name__} 실행 완료시간 : {end_time}') ## 함수 이름, 종료 시간 출력
        print(f'총 실행시간 {end_time-start_time}') ## 실행시간 출력
    return wrapper

@run_time
def f(string):
    '''
    Just Function
    '''
    print(string)
    print('Sleeping')
    time.sleep(3)
    
f('Good Night')

 


3) 여러 데코레이터 사용하기

여러 데코레이터를 함수에 적용할 수도 있다. 다음은 실행 시간과 더불어서 함수의 설명(Description)을 출력하는 데코레이터 document를 추가한 것이다.

 

def run_time(func):
    def wrapper():
        start_time = time.time() ## 함수 시작 시간 저장
        print(f'{func.__name__} 실행 시작시간 : {start_time}') ## 함수 이름, 실행 시작 시간 출력
        func() ## 함수 실행
        end_time = time.time() ## 함수 종료 시간 저장
        print(f'{func.__name__} 실행 완료시간 : {end_time}') ## 함수 이름, 종료 시간 출력
        print(f'총 실행시간 {end_time-start_time}') ## 실행시간 출력
    return wrapper

def document(func):
    def wrapper():
        print(func.__doc__) ## 함수 설명 출력
        func() ## 함수 
    return wrapper
    

@run_time
@document
def f():
    '''
    Just Function
    '''
    print('Sleeping')
    time.sleep(3)
    
f()

 

 

만약 @를 사용하지 않는다면 다음과 같이 작성해야 합니다.

 

def run_time(func):
    def wrapper():
        start_time = time.time() ## 함수 시작 시간 저장
        print(f'{func.__name__} 실행 시작시간 : {start_time}') ## 함수 이름, 실행 시작 시간 출력
        func() ## 함수 실행
        end_time = time.time() ## 함수 종료 시간 저장
        print(f'{func.__name__} 실행 완료시간 : {end_time}') ## 함수 이름, 종료 시간 출력
        print(f'총 실행시간 {end_time-start_time}') ## 실행시간 출력
    return wrapper

def document(func):
    def wrapper():
        print(func.__doc__) ## 함수 설명 출력
        func() ## 함수 
    return wrapper
    
def f():
    '''
    Just Function
    '''
    print('Sleeping')
    time.sleep(3)
    
run_time_document = run_time(document(f))
run_time_document()

 


이번 포스팅에서는 데코레이터에 대해서 알아보았다. 실제로 앞의 사례만 가지고는 데코레이터의 필요성을 잘 못느낄 수 있다. 하지만 실행 시간을 출력하고자 하는 함수가 많다고 생각해보자. 데코레이터가 없었다면 매 함수마다 실행시간을 출력하는 코드를 추가해야 할 것이다. 데코레이터는 큰 프로젝트에서 함수를 꾸미고자 할 때 진가가 발휘된다.

 

또한 데코레이터는 함수만 꾸며주는 것이 아니라 파이썬을 잘해보이는 것처럼 꾸며줄 수도 있다.


댓글


맨 위로