파이썬 데코레이터에게 추가 인수를 전달하려면 어떻게 해야 합니까?
아래와 같은 데코레이터가 있습니다.
def myDecorator(test_func):
return callSomeWrapper(test_func)
def callSomeWrapper(test_func):
return test_func
@myDecorator
def someFunc():
print 'hello'
나는 이 데코레이터를 개선하여 아래와 같은 또 다른 주장을 받아들이고 싶습니다.
def myDecorator(test_func,logIt):
if logIt:
print "Calling Function: " + test_func.__name__
return callSomeWrapper(test_func)
@myDecorator(False)
def someFunc():
print 'Hello'
하지만 이 코드는 오류를 범합니다.
TypeError: myDecorator()는 정확히 2개의 인수(1개)를 사용합니다.
기능이 자동으로 전달되지 않는 이유는 무엇입니까?데코레이터 기능에 기능을 명시적으로 전달하려면 어떻게 해야 합니까?
데코레이터를 함수처럼 호출하기 때문에 실제 데코레이터인 다른 함수를 반환해야 합니다.
def my_decorator(param):
def actual_decorator(func):
print("Decorating function {}, with parameter {}".format(func.__name__, param))
return function_wrapper(func) # assume we defined a wrapper somewhere
return actual_decorator
외부 함수에는 사용자가 명시적으로 전달하는 인수가 주어지며 내부 함수를 반환해야 합니다.내부 기능은 장식할 기능을 전달하고 수정된 기능을 반환합니다.
일반적으로 장식자가 래퍼 기능으로 포장하여 기능 동작을 변경하기를 원합니다.함수를 호출할 때 선택적으로 로깅을 추가하는 예제는 다음과 같습니다.
def log_decorator(log_enabled):
def actual_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
if log_enabled:
print("Calling Function: " + func.__name__)
return func(*args, **kwargs)
return wrapper
return actual_decorator
그functools.wraps
call은 이름이나 docstring과 같은 것들을 래퍼 함수에 복사하여 원래 함수와 더 유사하게 만듭니다.
사용 예시:
>>> @log_decorator(True)
... def f(x):
... return x+1
...
>>> f(4)
Calling Function: f
5
단지 다른 관점을 제공하기 위해: 구문.
@expr
def func(...): #stuff
와 동치입니다.
def func(...): #stuff
func = expr(func)
특히.expr
당신이 좋아하는 건 뭐든지 될 수 있어요, 콜레블로 평가한다면요.특히.expr
장식가 공장이 될 수 있습니다. 몇 가지 매개 변수를 제공하면 장식가가 제공됩니다.그래서 당신의 상황을 이해하는 더 좋은 방법은
dec = decorator_factory(*args)
@dec
def func(...):
다음으로 단축할 수 있습니다.
@decorator_factory(*args)
def func(...):
그럼요, 이렇게 보이니까.decorator_factory
장식가인데 사람들이 그걸 반영해서 이름을 짓는 경향이 있거든요간접적인 수준을 따르려고 하면 혼란스러울 수 있습니다.
장식가를 하는 또 다른 방법.저는 이 방법이 제 머리를 감싸기에 가장 쉽다고 생각합니다.
class NiceDecorator:
def __init__(self, param_foo='a', param_bar='b'):
self.param_foo = param_foo
self.param_bar = param_bar
def __call__(self, func):
def my_logic(*args, **kwargs):
# whatever logic your decorator is supposed to implement goes in here
print('pre action baz')
print(self.param_bar)
# including the call to the decorated function (if you want to do that)
result = func(*args, **kwargs)
print('post action beep')
return result
return my_logic
# usage example from here on
@NiceDecorator(param_bar='baaar')
def example():
print('example yay')
example()
데코레이터 인수를 선택 사항으로 만들 수 있는 유용한 트릭을 추가하고 싶습니다.또한 데코레이터를 재사용하고 네스팅을 줄일 수 있습니다.
import functools
def myDecorator(test_func=None,logIt=None):
if test_func is None:
return functools.partial(myDecorator, logIt=logIt)
@functools.wraps(test_func)
def f(*args, **kwargs):
if logIt==1:
print 'Logging level 1 for {}'.format(test_func.__name__)
if logIt==2:
print 'Logging level 2 for {}'.format(test_func.__name__)
return test_func(*args, **kwargs)
return f
#new decorator
myDecorator_2 = myDecorator(logIt=2)
@myDecorator(logIt=2)
def pow2(i):
return i**2
@myDecorator
def pow3(i):
return i**3
@myDecorator_2
def pow4(i):
return i**4
print pow2(2)
print pow3(2)
print pow4(2)
이제 함수를 호출하려면function1
장식을 달고decorator_with_arg
이 경우 함수와 장식가 모두 논쟁을 벌입니다
def function1(a, b):
print (a, b)
decorator_with_arg(10)(function1)(1, 2)
언급URL : https://stackoverflow.com/questions/10176226/how-do-i-pass-extra-arguments-to-a-python-decorator
'programing' 카테고리의 다른 글
PowerShell에 터미네이터가 없습니다. " (0) | 2023.10.16 |
---|---|
자바스크립트:바이트 배열의 새 탭에서 PDF 열기 (0) | 2023.10.16 |
malloc()는 연속된 메모리 블록을 할당합니까? (0) | 2023.10.16 |
Spring Boot 애플리케이션에서 베어러 인증을 활성화하는 방법은? (0) | 2023.10.11 |
마스터의 GTID가 슬레이브와 다를 경우 어떻게 경고를 받을 수 있습니까? (0) | 2023.10.11 |