간단한 데커레이터 구현하기
728x90
import time
def clock(func):
def clocked(*args): # 내부 함수 clocked() 가 임의 개수의 위치 인수를 받을 수 있도록 정의한다.
t0 = time.perf_counter()
result = func(*args) # clocked() 에 대한 클로저에 자유 변수 func가 들어가야 이 코드가 작동한다.
elapsed = time.perf_counter()
name = func.__name__
arg_str = ', '.join(repr(arg) for arg in args)
print('[%0.8fs] %s(%s) -> %r' % (elapsed, name, arg_str, result))
return result
return clocked
이함수는 데커레이트된 함수를 호출할 때마다 시간을 측정해서 실행에 소요된 시간, 전달 된 인수,
반환값을 출력하는 데커레이터다.
@clock
def factorial(n):
return 1 if n < 2 else n*factorial(n-1)
위 코드는 실제로 다음 코드로 실행된다.
def factorial2(n):
return 1 if n < 2 else n*factorial2(n-1)
따라서 앞의 두 예제에서는 clock()은 factorial() 함수를 func인수로 받는다.
그후 clocked() 함수를 만들어서 반환하는데, 파이썬 인터프리터가 내부적으로 clocked()를
factorial에 할당했다. 실제로 clockdeco_demo 모듈을 임포트해서 factorial의
__name__ 속성을 조사해보면 다음과 같은 결과가 나온다.
import clockdeco_demo
clockdeco_demo.factorial.__name__
--> 'clocked'
그러므로 factorial은 이제 실제로 clocked()함수를 참조한다.
이제부터 factorial(n)을 호출하면 clocked(n)이 실행된다.
본질적으로 clocked() 함수는 다음과 같은 연산을 수행한다.
- 초기 시각 t0를 기록한다.
- 원래의 factorial() 함수를 호출하고 결과를 저장한다.
- 흘러간 시간을 계산한다.
- 수집한 데이터를 포맷하고 출력한다.
- 2번째 단계에서 저장한 결과를 반환한다.
이 예제 함수는 전형적인 데커레이터 작동 방식을 보여준다.
데커레이트된 함수를 동일한 인수를 받는 함수로 교체하고, (일반적으로) 데커레이트된 함수가
반환해야 하는 값을 반환하면서 추가적인 처리를 수행한다.
728x90
'Python > python - pythonic' 카테고리의 다른 글
약한참조 (2) | 2020.12.02 |
---|---|
del 과 가비지 컬렉션 (0) | 2020.12.02 |
nonlocal 선언 이 필요한 이유 (0) | 2020.11.28 |
클로저 함수 (0) | 2020.11.28 |
변수 범위 규칙 (0) | 2020.11.27 |
댓글
이 글 공유하기
다른 글
-
약한참조
약한참조
2020.12.02 -
del 과 가비지 컬렉션
del 과 가비지 컬렉션
2020.12.02 -
nonlocal 선언 이 필요한 이유
nonlocal 선언 이 필요한 이유
2020.11.28 -
클로저 함수
클로저 함수
2020.11.28