본문 바로가기

코딩/Python

[Python/파이썬] 데코레이터(Decorator) 2편 : 매개변수 있는 함수에 데코레이터 적용

반응형

이전 포스팅 : 2021.07.14 - [코딩/Python] - [Python/파이썬] 함수 속의 함수 - 데코레이터(Decorator) 1편

 

  이전 포스팅에서는 데코레이터의 개념과 기본 사용법에 대해서 정리했다. 이번에는 매개변수가 있는 함수에 데코레이터를 어떻게 사용하는지에 대해 정리해보려고 한다. 함수에 매개변수가 있는 경우는 크게 2가지인데 하나는 일반적인 매개변수 타입인 경우, 두번째는 매개변수가 가변 인자, 키워드 인자인 경우이다.

 

 

 

Case1. 일반적인 매개변수 함수인 경우

 

  지난 편에서 사용했던 경주마 예시를 그대로 가져왔다. 1편에서는 매개변수가 없었지만 이번 예시에는 경주마의 번호를 나타내는 number와 달리는 총 거리를 표시한 distance라는 매개변수를 지정하여 함수를 정의하였다.

 

 

<코드>

#decorator가 없는 경우의 본 함수 정의
import time

def race(number : int, distance : int):
    print(str(number)+"번 경주마가 출발했습니다.")
    for n in range(0, distance):
        print(str(n)+"km 달리는 중입니다.")
        time.sleep(0.5)
    print("경주마가 결승선에 도착했습니다.")

 

  이전 편에서 파이썬의 데코레이터는 로그를 기록하거나 함수가 동작하는 시간을 측정하는 방식으로 많이 사용한다고 언급했었다. 그래서 이번엔 위 race라는 함수가 동작하는 시간을 측정하는 decorator를 작성해볼 것이다.

 

 

<코드>

#데코레이터 함수 정의
def decoFunction(inputFunc): #원래 함수를 매개변수로 입력 받음
    def clock(number, distance): #deco가 되는 clock 함수에 매개변수 2개(본 함수와 동일)
        start_time = time.time() #함수 시작 시간 측정
        inputFunc(number, distance) #원래 함수 
        end_time = time.time() #함수 종료 시간 측정
        print("걸린시간 : ", end_time - start_time) #함수 종료 시간 - 함수 시작 시간
    return clock #wrapper라는 함수를 리턴

 

  decoFunction의 매개변수는 실제 동작하는 원래 함수 race다.(inputFunc = race) 원래 함수 race에 매개변수가 있으므로 decoFucntion 내부 함수 clock에도 동일하게 매개변수를 지정해주면 된다. 위 코드를 보면 알겠지만 clock(number, distance) 와 inputFunc(number, distance)로 동일한 숫자로 매개변수를 지정했다. 따라서, 매개변수 숫자가 다르면 에러가 난다. 앞에서 설명한 부분을 도식화하면 하단 이미지와 같다.

 

< 매개변수가 있는 함수에 데코레이터 적용할 경우 >

 

 

  전체 코드 및 결과는 아래 코드블록을 참고하자.. race 함수 위에 @decoFunction을 표시함으로써 race가 decorator를 통해 함수 동작 시간을 측정할 수 있다.

 

 

<전체 코드>

import time

#데코레이터 함수 정의
def decoFunction(inputFunc): #원래 함수를 매개변수로 입력 받음
    def clock(number, distance):
        start_time = time.time()
        inputFunc(number, distance) #원래 함수 
        end_time = time.time()
        print("걸린시간 : ", end_time - start_time)
    return clock #wrapper라는 함수를 리턴

#데코레이터 사용
@decoFunction
def race(number : int, distance : int):
    print(str(number)+"번 경주마가 출발했습니다.")
    for n in range(0, distance):
        print(str(n)+"km 달리는 중입니다.")
        time.sleep(0.5)
    print("경주마가 결승선에 도착했습니다.")


if __name__ == "__main__":
    race(1, 7)

 

<결과>

경주마가 달린 후 걸린 시간 측정

 

 

 

Case2. 원래 함수의 매개변수가 가변 인자 함수, 키워드 인자 함수인 경우

 

  Case2를 정리하기전에 가변 인자 함수와 키워드 인자 함수에 대한 내용을 알아야 한다. 얼마 전에 가변 인자 함수, 키워드 인자에 대해서 정리한 포스팅이 있다. 해당 내용은 설명을 생략하고 참고 링크로 대체한다.

(참고링크 : 2021.06.26 - [코딩/Python] - [Python/파이썬] 가변 인자 함수(*args), 키워드 인자(**kargs))

 

   2번째 Case를 설명 하기 위해 입력 된 매개변수에 따라 평균을 계산해주는 예시 코드를 작성해보았다. 해당 코드는 코딩 도장의 42.2 단원을 참고했다.

 

 

<전체 코드>

#아래 함수에서 평균을 계산한 결과를 출력해주는 데코레이터
def decoFunction(inputFunc):
    def printNum(*args, **kwargs):
        r = inputFunc(*args, **kwargs)
        print(inputFunc.__name__)
        print("평균 : ", r)
    return printNum
    
#가변 인자 함수에 데코레이터 적용
@decoFunction
def average1(*args): 
    print("가변 인자 함수 평균 계산")
    sum = 0
    num = len(args) #튜플 갯수
    for i in args: #튜플 반복문
        sum = sum + i
    average = sum/num
    return average

#키워드 인자 함수에 데코레이터 적용
@decoFunction
def average2(**kargs):
    print("가변 인자 함수 평균 계산")
    sum = 0
    num = len(kargs) #딕셔너리 갯수
    for i in kargs.values(): #딕셔너리에서 value값만 반복
        sum = sum + i
    average = sum/num
    return average

if __name__ == "__main__":

    average1(1,2,3,4,5) #가변 인자 함수 사용
    average2(x=1, y=5, z=10) #키워드 인자 함수 사용

 

<결과>

가변 인자 함수 평균 계산
average1
평균 :  3.0
키워드 인자 함수 평균 계산
average2
평균 :  5.333333333333333

 

  원래 함수의 매개변수가 가변인자, 키워드인자인 경우에도 기본적으로 decorator 구성 방법은 위 Case1과 동일하다. decorator의 내부 함수에 동일하게 가변인자 *args와 **kwargs를 넣어주면 된다. 

 

 

  클래스의 메서드 함수에 데코레이터를 적용할 경우에는 self를 넣어주면 되는데  위 방법과 크게 다르지 않아 자세한 설명은 생략한다. 해당 내용은 하단 참고 링크(코딩도장)을 참고하면 좋을 것 같다.

 


참고링크 : https://dojang.io/mod/page/view.php?id=2428 

 

728x90