def is_multiple(x):여기서 real_decorator는 wrapper 을 is_multiple에게 반환하게 되는데, wrapper자체를 반환하게 되는건가요? 어떤 특정 값을 반환하게 되나요? 이 부분이 잘 이해가 가지 않습니다.
def real_decorator(func):
def wrapper(a,b):
r = func(a,b)
if r % x == 0:
print('{0}의 반환값은 {1}의 배수입니다.'.format(func.__name__,x))
else:
print('{0}의 반환값은 {1}의 배수입니다.'.format(func.__name__, x))
return r
return wrapper
return real_decorator
<function is_multiple.<locals>.real_decorator.<locals>.wrapper at 0x7fa7f83be670>
print를 사용하면 이렇게 나오던데, 어떤 의미를 가지고 있는건가요?
기본 데코레이터 구조부터 반복해서 연습해서 구조를 외우는 게 가장 좋습니다. 그러고 나서 매개변수가 있는 데코레이터를 이해하면 더 좋습니다.
3의 배수를 판단하는 함수, 5의 배수를 판단하는 함수, 17의 배수를 판단하는 함수 등... 다양한 요구사항을 만족하기 위해 함수를 만든다면 만들어야 하는 함수의 개수가 끝이 없을 겁니다. 그럴 때 함수의 기본 동작을 바꿀 수 있게 하는 것이 데코레이터입니다.
func는 호출할 함수를 매개변수로 받는 것이죠. add 함수를 매개변수로 받았다면 데코레이터 내부에서
r = func(a, b)는
r = add(a, b)가 됩니다.
add(10, 20)을 호출했다면
r = add(10, 20)이 됩니다.
따라서 r은 30이 됩니다.
is_multiple(x)로 매개변수를 정했으므로
@is_multiple(3)은 x = 3이 됩니다.
if r % x == 0:은
r = 30, x = 3이므로
if 30 % 3 == 0:이 됩니다.
이에 따라 add 함수를 변경하지 않고도 데코레이터를 통해 3의 배수인지 확인하는 기능을 add 함수에 추가할 수 있게 된 것이죠.
func.__name__은 호출한 함수의 이름입니다. add 함수를 호출했으니 func.__name__의 결과는 add가 됩니다.
print로 출력한 것은 def 3개가 차례대로 선언되어 있으니 그 순서를 보여줄 뿐입니다.
데코레이터는 고급 기능이고, 파이썬 코딩에서는 사용 빈도가 높은 기능은 아닙니다. 다만, 알면 불필요한 함수를 많이 만들지 않아도 되는 도구입니다.
이런 게 있었지 하고 넘어가거나 데코레이터를 많이 만들고, 사용하면서 구조 자체를 외우는 수밖에 없습니다. 암기 이후에 이해가 생기기 때문입니다. 암기 없는 이해는 없으니까요.
함수도 구조가 간단해서 그렇지만, 함수의 구조를 암기하고 자주 쓰면서 이해하게 되는 것이죠. 프로그래밍 언어는 함수를 매번 호출하니까 그만큼 자주 사용하니 이해하기 쉽다고 느끼는 것입니다. 많이 사용하는 것 외에는 정도가 없습니다. 예제 안 보고 데코레이터 100개 만들어 보면 암기와 이해가 됩니다. 프로그래머는 하루 종일 코딩하면서 반복문을 10개, 20개씩 사용하고, 조건문도 20개 이상 만들겠죠. 너무 적게 만드나요. 그렇게 기본 문법 구조를 100번, 1000번, 10000번 사용하는 겁니다. 데코레이터나 코루틴도 그렇습니다. 입문 단계에서는 이런 게 있어 정도면 충분합니다. 중급 이상으로 가면 반드시 사용 빈도가 올라가게 되어 있고요. 그때 복습해도 됩니다. 언어를 마스터한다고 접근하기보단 만들고 싶은 걸 만드는 데 이용하세요.(서로 조금 모순된 이야기 같지만...)