~15 min · wraps, functools, metadata, introspection
Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
처음 짤 때 만나는 버그
lesson 1 의 순진한 decorator 에는 문제 — 감싸진 함수가 이름, docstring, 시그니처 잃어. hello.__name__ 이 이제 'wrapper'. help(hello) 가 wrapper 의 docstring 표시, 원래 거 X. 함수 introspect 하는 도구 — 디버거, 문서 생성기, inspect.signature — 가 wrapper 보고 진짜 함수 못 봄.
functools.wraps — 메타데이터 복사
해결책 한 줄 — wrapper 에 @functools.wraps(fn). __name__, __doc__, __module__, __qualname__, __annotations__, __wrapped__ 를 원래 함수에서 wrapper 로 복사. 이제 help(hello) 가 원래 docstring 표시, hello.__name__ 이 'hello'.
__wrapped__ — 원래 거에 접근
wraps 가 추가하는 한 가지 — 원래 함수 가리키는 __wrapped__ 속성. inspect.signature 와 inspect.unwrap 이 이거 사용. wrapper 우회하고 원래 거 호출해야 하면 wrapped_fn.__wrapped__().
원칙: wrapper 에 항상 @functools.wraps. 진짜 단점 없고, 빼면 introspection 깨짐 — 디버깅 어려운 방식으로. 근육 기억 만들어.
wraps 가 보존 *못* 하는 것
wrapper 의 *시그니처* 는 바이트코드 레벨에선 여전히 (*args, **kwargs). inspect.signature(hello) 는 __wrapped__ 덕분에 작동, 근데 wrapper 의 실제 __code__ 는 여전히 뭐든 받아. 대부분 목적엔 OK. 중요한 경우 (wrapper 레벨에서 엄격한 인자 검증) 는 드물어.
lesson 1 의 count_calls decorator 에 @functools.wraps 추가. (a) __name__, __doc__ 보존되는 거, (b) inspect.signature 여전히 정확, (c) wrapped_fn.__wrapped__ 가 원래 함수 반환 — 보여. 그 다음 wraps *없이* 두 번째 버전 만들어서 repr() 와 help() 출력 차이 보여.
Progress
Progress is local-only — sign in to sync across devices.