작성
·
126
·
수정됨
0
안녕하세요 강사님!
좋은 강의 정말 잘 듣고 있습니다. 지난 질문에도 친절하게 답변 달아주셔서 감사의 말씀 드립니다.
이번 메타프로그밍 3.1절을 들으면서 잘 이해가 안되는 부분이 있어서 이렇게 질문글을 작성합니다.
질문은 다음과 같습니다.
Q1. attach_wrapper가 return 하는 func는 누구인가? 최종적으로 그 func는 누가 받는가?
def attach_wrapper(obj, func=None):
if func is None:
return partial(attach_wrapper, obj)
setattr(obj, func.__name__, func)
return func
위의 def attach_wrapper
가 @attach_wrapper(wrapper)
형태로 데코레이트하면, func=None
일 때 partial()
을 통해서 def attach_wrapper
함수 객체 본인을 return
해서 첫번째 인자인 obj
를 wrapper
로 고정시키는 것까지 이해를 했습니다.
func=None
이 아니면 setattr()
을 통해, obj
가 갖고 있는 어트리뷰트 func
의 이름을 인자로 받은 func
로 값을 셋팅하는 것까지도 이해를 했습니다.
그런데 최종적으로 return
되는 게 func
라는 것이 잘 이해가 되지 않습니다. return
되는 func
를 누가 받는걸까요?
func
를 유추하기까지 저의 사고 흐름은 아래와 같았습니다.
@attach_wrapper(wrapper)
def set_level(newlevel):
nonlocal level
level = newlevel
def set_level
이 데코레이트 되는 내부 사정은 set_level = attach_wrapper(wrapper)(set_level)
이 될텐데요.
set_level = attach_wrapper(wrapper)(set_level)
에서 attach_wrapper(wrapper)
는 partial()
을 통해 def attach_wrapper
본체가 return
되었기 때문에, 데코레이트 되는 내부 사정을 달리 표현하면 set_level = attach_wrapper(obj=wrapper, func=set_level)
라고 이해를 했습니다.
그러면.. attach_wrapper(obj=wrapper, func=set_level)
가 return
하는 게 func
인데, set_level = func
이니까.. set_level = set_level
이 되는건가요?
추가 질문def attach_wrapper
함수에서 return func
를 주석처리 하고 실행을 해도 결과가 똑같이 나오는데 이유를 잘 모르겠습니다.. 어째서 return func
가 아무런 효용이 없었던 걸까요..?
혹시 제가 잘 못 이해한 부분이 있다면 어김없이 피드백 부탁드리겠습니다!
(아래에는 출력 결과물을 첨부하였습니다.)
"""
# return func 주석 처리 후 결과
DEBUG:__main__:add
DEBUG:__main__:Add called
WARNING:__main__:Add called
DEBUG:__main__:countdown
CRITICAL:__main__:countdown
DEBUG:__main__:countdown2
CRITICAL:__main__:countdown2
5
5
5
countdown 0.009128093719482422
countdown 0.007673978805541992
countdown2 0.0056438446044921875
countdown2 0.005079030990600586
---
# 원본 코드 실행 결과
DEBUG:__main__:add
DEBUG:__main__:Add called
WARNING:__main__:Add called
DEBUG:__main__:countdown
CRITICAL:__main__:countdown
DEBUG:__main__:countdown2
CRITICAL:__main__:countdown2
5
5
5
countdown 0.007693052291870117
countdown 0.006663084030151367
countdown2 0.005110979080200195
countdown2 0.0052149295806884766
"""
답변 1
0
안녕하세요, 인프런 AI 인턴입니다.
attach_wrapper
함수의 return func
부분은 이 함수를 데코레이터로 사용할 때 중요한 역할을 합니다. 함수 데코레이터는 보통 원래 함수를 받아서 어떤 처리를 한 뒤에 함수를 반환하는 구조를 가집니다. 이 때, 반환되는 함수가 원래의 함수이거나 원래 함수에 어떤 기능이 추가된 새로운 함수가 될 수 있습니다.
return func
가 있을 경우, 데코레이터는 func
함수에 추가적인 처리(예: 함수에 어떤 속성을 추가하는 등)를 한 후에 원래 함수 func
를 그대로 반환합니다. 이로 인해 func
의 정의가 변경되거나 추가된 속성을 유지하면서, 함수의 호출 가능성을 그대로 유지할 수 있습니다.
@attach_wrapper(wrapper)
를 사용한 경우, return func
는 setattr
을 통해 obj
에 함수 func
의 이름으로 속성을 추가한 후에 원래의 함수 func
를 반환함으로써, 원래 함수 func
에 대한 참조를 유지하게 합니다. 따라서 set_level = attach_wrapper(wrapper, func=set_level)
에서 func
는 set_level
자기 자신을 가리키고, 이는 setattr
을 통해 wrapper
에 set_level
함수를 속성으로 추가한 후, set_level
함수 자체를 반환하는 것을 의미합니다.
추가 질문에 대한 답변으로, return func
을 주석 처리하고 실행해도 결과가 같게 나오는 것은 특정 상황에서는 반환값을 명시적으로 사용하지 않기 때문일 수 있습니다. 예를 들어, 만약 attach_wrapper
가 데코레이터로 사용되어 함수에 추가적인 처리만 하고, 실제로 그 함수가 다시 사용되지 않는다면 (즉, 반환된 함수를 다른 곳에서 호출하거나 참조하지 않는다면) return func
가 생략되어도 코드 실행에 큰 차이가 없을 것입니다. 그러나, 함수의 반환값을 기대하거나 이후에 해당 함수를 다시 사용할 필요가 있는 경우에는 return func
이 중요한 역할을 합니다. 따라서 특정 상황에 따라 return func
의 유무가 결과에 영향을 주지 않을 수도 있으나, 일반적으로는 함수 데코레이터에서는 원래 함수를 반환하는 것이 좋은 관례입니다.
임의의 코드나 상황에 따라서는 return func
이 명확하게 필수적인 역할을 하지 않을 수 있습니다만, 데코레이터의 기본적인 구조와 원칙을 따르는 것이 바람직합니다. 이해가 되지 않는 부분이 있다면 추가적인 질문을 주시길 바랍니다.