42.7 연습문제: 데코레이터로 매개변수의 자료형 검사하기

다음 소스 코드에서 데코레이터 type_check를 작성하세요. type_check는 함수의 매개변수가 지정된 자료형(클래스)이면 함수를 정상적으로 호출하고, 지정된 자료형과 다르면 RuntimeError 예외를 발생시키면서 '자료형이 다릅니다.' 에러 메시지를 출력해야 합니다. 여기서 type_check에 지정된 첫 번째 int는 호출할 함수에서 첫 번째 매개변수의 자료형을 뜻하고, 두 번째 int는 호출할 함수에서 두 번째 매개변수의 자료형을 뜻합니다.

practice_decorator.py

                                                                   
...
                                                                   
 
@type_check(int, int)
def add(a, b):
    return a + b
 
print(add(10, 20))
print(add('hello', 'world'))

실행 결과

30
Traceback (most recent call last):
  File "C:\project\practice_decorator.py", line 16, in <module>
    print(add('hello', 'world'))
  File "C:\project\practice_decorator.py", line 7, in wrapper
    raise RuntimeError('자료형이 올바르지 않습니다.')
RuntimeError: 자료형이 올바르지 않습니다.

정답

def type_check(type_a, type_b):
    def real_decorator(func):
        def wrapper(a, b):
            if isinstance(a, type_a) and isinstance(b, type_b):
                return func(a, b)
            else:
                raise RuntimeError('자료형이 올바르지 않습니다.')
        return wrapper
    return real_decorator

해설

데코레이터 type_check를 보면 @type_check(int, int)와 같이 int 두 개를 넣고있습니다. 따라서 매개변수가 있는 데코레이터입니다.

먼저 def type_check(type_a, type_b):와 같이 데코레이터가 사용할 매개변수를 지정합니다. 그리고 type_check 함수 안에서는 실제 데코레이터 역할을 하는 real_decorator를 만듭니다. 특히 이 함수에서 def real_decorator(func):와 같이 호출할 함수를 매개변수로 받습니다.

add 함수는 def add(a, b):와 같이 매개변수를 두 개 받으므로 wrapper 함수도 def wrapper(a, b):와 같이 매개변수를 두 개 지정해줍니다. 그다음에 isinstance를 사용하여 호출할 함수의 매개변수가 데코레이터에 지정한 자료형(클래스)의 인스턴스인지 확인합니다. 인스턴스가 맞으면 return func(a, b)와 같이 함수를 호출한 뒤 결과를 반환하고, 인스턴스가 아니면 raise RuntimeError('자료형이 올바르지 않습니다.')와 같이 예외를 발생시키면서 에러 메시지를 출력합니다.

마지막으로 wrapper 함수를 다 만들었으면 return으로 wrapper 함수를 반환하고, real_decorator 함수를 다 만들었으면 return으로 real_decorator 함수를 반환하면 됩니다.