我有一个由装饰器转移变量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
以下是对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
带参数的装饰器应该返回一个函数,该函数将接受一个函数,并返回另一个函数
def decorator_factory(argument):
def decorator(function):
def wrapper(*args, **kwargs):
"""
add somhting
"""
return function(*args, **kwargs)
return wrapper
return decorator
或者你可以使用functools模块的部分
def decorator(function =None,*,argument ):
if function is None :
return partial(decorator,argument=argument)
def wrapper(*args, **kwargs):
"""
add somhting
"""
return function(*args, **kwargs)
return wrapper
在第二个选项中,确保你像这样传递参数:
@decorator(argument = 'args')
def func():
pass
例如,我在下面创建了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
假设你有一个函数
def f(*args):
print(*args)
你想要添加一个接受参数的装饰器,就像这样:
@decorator(msg='hello')
def f(*args):
print(*args)
这意味着Python将对f进行如下修改:
f = decorator(msg='hello')(f)
因此,部件装饰器(msg='hello')的返回值应该是一个包装器函数,它接受函数f并返回修改后的函数。然后可以执行修改后的函数。
def decorator(**kwargs):
def wrap(f):
def modified_f(*args):
print(kwargs['msg']) # use passed arguments to the decorator
return f(*args)
return modified_f
return wrap
所以,当你调用f时,就像你在做:
装饰(味精= '你好')(f) (args)
=== wrap(f)(args) === modified_f(args)
但是modified_f可以访问传递给装饰器的kwargs
的输出
f(1,2,3)
将会是:
hello
(1, 2, 3)
如果函数和装饰器都必须接受参数,可以采用下面的方法。
例如,有一个名为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的参数