我有一个由装饰器转移变量insurance_mode的问题。我将通过以下装饰器语句来实现:
@execute_complete_reservation(True)
def test_booking_gta_object(self):
self.test_select_gta_object()
但不幸的是,这种说法并不管用。也许也许有更好的办法来解决这个问题。
def execute_complete_reservation(test_case,insurance_mode):
def inner_function(self,*args,**kwargs):
self.test_create_qsf_query()
test_case(self,*args,**kwargs)
self.test_select_room_option()
if insurance_mode:
self.test_accept_insurance_crosseling()
else:
self.test_decline_insurance_crosseling()
self.test_configure_pax_details()
self.test_configure_payer_details
return inner_function
例如,我在下面创建了multiply(),它可以接受一个参数或不接受参数,也可以不接受装饰器的括号,我在下面创建了sum():
from numbers import Number
def multiply(num=1):
def _multiply(func):
def core(*args, **kwargs):
result = func(*args, **kwargs)
if isinstance(num, Number):
return result * num
else:
return result
return core
if callable(num):
return _multiply(num)
else:
return _multiply
def sum(num1, num2):
return num1 + num2
现在,我把@multiply(5)放在sum()上,然后调用sum(4,6),如下所示:
# (4 + 6) x 5 = 50
@multiply(5) # Here
def sum(num1, num2):
return num1 + num2
result = sum(4, 6)
print(result)
那么,我可以得到如下结果:
50
接下来,我把@multiply()放在sum()上,然后调用sum(4,6),如下所示:
# (4 + 6) x 1 = 10
@multiply() # Here
def sum(num1, num2):
return num1 + num2
result = sum(4, 6)
print(result)
或者,我把@multiply放在sum()上,然后调用sum(4,6),如下所示:
# 4 + 6 = 10
@multiply # Here
def sum(num1, num2):
return num1 + num2
result = sum(4, 6)
print(result)
那么,我可以得到如下结果:
10
在我的实例中,我决定通过一行lambda来解决这个问题,以创建一个新的decorator函数:
def finished_message(function, message="Finished!"):
def wrapper(*args, **kwargs):
output = function(*args,**kwargs)
print(message)
return output
return wrapper
@finished_message
def func():
pass
my_finished_message = lambda f: finished_message(f, "All Done!")
@my_finished_message
def my_func():
pass
if __name__ == '__main__':
func()
my_func()
执行时,输出:
Finished!
All Done!
也许不像其他解决方案那样可扩展,但对我来说是可行的。
定义这个decoratorize函数来生成定制的decorator函数:
def decoratorize(FUN, **kw):
def foo(*args, **kws):
return FUN(*args, **kws, **kw)
return foo
可以这样用:
@decoratorize(FUN, arg1 = , arg2 = , ...)
def bar(...):
...
如果函数和装饰器都必须接受参数,可以采用下面的方法。
例如,有一个名为decorator1的装饰器,它接受一个参数
@decorator1(5)
def func1(arg1, arg2):
print (arg1, arg2)
func1(1, 2)
现在,如果decorator1参数必须是动态的,或者在调用函数时传递,
def func1(arg1, arg2):
print (arg1, arg2)
a = 1
b = 2
seconds = 10
decorator1(seconds)(func1)(a, b)
在上面的代码中
Seconds是decorator1的参数
A b是func1的参数
以下是对t.dubrownik的回答稍加修改的版本。为什么?
作为通用模板,您应该返回原始函数的返回值。
这将改变函数的名称,这可能会影响其他装饰器/代码。
所以使用@functools.wraps():
from functools import wraps
def create_decorator(argument):
def decorator(function):
@wraps(function)
def wrapper(*args, **kwargs):
funny_stuff()
something_with_argument(argument)
retval = function(*args, **kwargs)
more_funny_stuff()
return retval
return wrapper
return decorator