我有一个由装饰器转移变量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
定义这个decoratorize函数来生成定制的decorator函数:
def decoratorize(FUN, **kw):
def foo(*args, **kws):
return FUN(*args, **kws, **kw)
return foo
可以这样用:
@decoratorize(FUN, arg1 = , arg2 = , ...)
def bar(...):
...
编写一个带参数和不带参数的装饰器是一个挑战,因为Python在这两种情况下期望完全不同的行为!许多答案都试图解决这个问题,下面是@norok2对答案的改进。具体来说,这种变化消除了locals()的使用。
下面是@norok2给出的相同示例:
import functools
def multiplying(f_py=None, factor=1):
assert callable(f_py) or f_py is None
def _decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return factor * func(*args, **kwargs)
return wrapper
return _decorator(f_py) if callable(f_py) else _decorator
@multiplying
def summing(x): return sum(x)
print(summing(range(10)))
# 45
@multiplying()
def summing(x): return sum(x)
print(summing(range(10)))
# 45
@multiplying(factor=10)
def summing(x): return sum(x)
print(summing(range(10)))
# 450
玩一下这段代码。
问题是用户必须提供键、值对的参数,而不是位置参数,并且第一个参数是保留的。
我猜你的问题是把参数传递给你的装饰师。这有点棘手,不简单。
下面是一个如何做到这一点的例子:
class MyDec(object):
def __init__(self,flag):
self.flag = flag
def __call__(self, original_func):
decorator_self = self
def wrappee( *args, **kwargs):
print 'in decorator before wrapee with flag ',decorator_self.flag
original_func(*args,**kwargs)
print 'in decorator after wrapee with flag ',decorator_self.flag
return wrappee
@MyDec('foo de fa fa')
def bar(a,b,c):
print 'in bar',a,b,c
bar('x','y','z')
打印:
in decorator before wrapee with flag foo de fa fa
in bar x y z
in decorator after wrapee with flag foo de fa fa
详见Bruce Eckel的文章。
这是curry函数的一个很好的用例。
curry函数本质上是延迟函数的调用,直到提供了所有输入。
这可以用于各种事情,如包装器或函数式编程。在本例中,让我们创建一个接受输入的包装器。
我将使用一个简单的包pamda,其中包含一个用于python的curry函数。这可以用作其他函数的包装器。
安装 Pamda:
pip install pamda
创建一个简单的带有两个输入的装饰函数:
@pamda.curry()
def my_decorator(input, func):
print ("Executing Decorator")
print(f"input:{input}")
return func
使用提供给目标函数的第一个输入应用你的装饰器:
@my_decorator('Hi!')
def foo(input):
print('Executing Foo!')
print(f"input:{input}")
执行你的包装函数:
x=foo('Bye!')
把所有东西放在一起:
from pamda import pamda
@pamda.curry()
def my_decorator(input, func):
print ("Executing Decorator")
print(f"input:{input}")
return func
@my_decorator('Hi!')
def foo(input):
print('Executing Foo!')
print(f"input:{input}")
x=foo('Bye!')
将:
Executing Decorator
input:Hi!
Executing Foo!
input:Bye!
在我的实例中,我决定通过一行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!
也许不像其他解决方案那样可扩展,但对我来说是可行的。