我正在使用装饰器: deferred_set_context 将功能模块,名称和时间设置为上下文字符串(基本上需要此上下文来跟踪多次调用 register_request < /强>)
@deferred_set_context()
def register_request(self, machine_model):
def deferred_set_context(name=None):
def __outer__(func):
context_name = name
if not context_name:
context_name = func.__name__
@defer.inlineCallbacks
def __inner__(*args, **kwargs):
r = None
with base.this_context_if_no_context(base.Context('%s.%s.%s' % (func.__module__, context_name,
datetime.utcnow().strftime(
'%Y-%m-%dT%H:%M:%S.%f')))):
r = yield func(*args, **kwargs)
defer.returnValue(r)
return __inner__
return __outer__
现在我需要设置将 machine_model 名称( register_request 的参数)传递给此装饰器: register_request 。像这样:
@deferred_set_context(name=machine_model)
def register_request(self, machine_model):
我该怎么做?
答案 0 :(得分:1)
请注意,以下两个代码段是等效的
# first
@decorator
def func():
pass
# second
def func():
pass
func = decorator(func)
你需要让你的装饰者把一个函数作为一个参数。如果要将name作为变量传递,那么它应该是装饰器返回的函数中的参数。
答案 1 :(得分:1)
假设您不想更改deferred_set_context
或register_request
的行为,您可以制作第二个shim装饰器,它会侦测正确的函数参数并将其传递给原始装饰器。< / p>
这样的事情:
def new_shim_decorator(register_request):
def wrapper(self, machine_model):
return deferred_set_context(machine_model)(self, machine_model)
return wrapper
@new_shim_decorator
def register_request(self, machine_model):
print("my_function called with {}".format(machine_model))
在我看来,这是一种hacky解决方案,因为这个装饰器代理原始装饰器需要知道传递给register_request
并反映它们的参数。
我更希望看到一个只有关键字的参数,可以选择get
- 来自shim decorator中的关键字参数字典或原始的:
def deferred_set_context_by_kwarg(kwarg_name):
def outer(func):
def wrapper(*args, **kwargs):
return deferred_set_context(name=kwargs.get(kwarg_name))(*args, **kwargs)
return wrapper
return outer
@deferred_set_context_by_kwarg('machine_model')
def register_request(self, *, machine_model):
print("my_function called with {}".format(machine_model))
注意*, machine_model
。 *
是一个Python 3功能,需要将machine_model
指定为关键字参数。这允许我们的deferred_set_context_by_kwarg
装饰器接受表示我们想要的关键字参数名称的字符串,并使用该名称来检索关键字参数值,并在每次函数调用时传递给deferred_set_context
。
答案 2 :(得分:0)
如果你确定你的函数register_request
总是使用相同的2个参数,那么在装饰器代码中选择它们。