데커레이터를 파싱할 때 파이썬은 함수를 가져와서 데커레이터 함수의 첫 번째 인수로 넘겨주는데 다른 인수를 받아서 데커레이터를 반환할 수는 없을가요?
답은, 인수를 받아 데커레이터를 반환하는 데커레이터 팩토리를 만들고 나서, 될 함수에 데커레이터 팩토리를 적용하면 됩니다.
#답에 대한 내용이 어려울 수 있으니 코드로 예시를 듭니다.
registry = []
def register(func):
print('running register(%s)' % func)
registry.append(func)
return func
@register()
def f1():
print('running f1()')
print('running main()')
print('registy ->', registry)
f1()
@register()
def f2():
print('running f2()')
def f3():
print('running f3()')
핵심은 register()가 decorate()를 반환하고, 데커레이트될 함수에 decorate()가 적용된다.
import registration_param
registration+param.registry
f2()함수만 registry에 남아 있으므로 register() 데커레이터 팩토리에 activate=False 인수를 전달했으므로 f1()에 적용된 register()를 일반 함수로 사용하려면 괄호문이 필요하고, f()를 registry에 추가하려면 register()(f)로, registry에서 제거하려면 register(activate=False)(f)로 호출해야하므로 괄호 구무을 이용해서 함수를 registry에 추가하거나 제거하는 예를 보여준다.
#나열된 registration_param 모듈 사용
from registration_param import *
registry
register()(f3)
registry
register(active=False)
registry
매개변수화된 데커레이터의 작동 방식은 상담히 복잡함으로 매개변수화된 데커레이터는 일반적으로 데커레이터된 함수를 대체하며 생성하기 위해 함수를 한 단계 더 내포한다.
#clock_param.py 모듈: 매개변수화된 clock() 데커레이터
import time
DEFAULT_FMT = '[{elapsed:0.8f}s] {name}({args}) -> {result}'
def clock(fmt=DEFAULT_FMT):
def decorate(func):
def clocked(*_args):
t0 =time.time()
_result = func(*_args)
elapsed = time.time() - t0
name = func.__name__
args = ', '.join(repr(arg) for arg in _args)
result = repr(_result)
print(fmt.format(**locals()))
return _result
return clocked
return decorate
if __name__ == '__main__'
@clock()
def snooze(seconds):
time.sleep(seconds)
for i in range(3):
snooze(.123)