我有一个由装饰器转移变量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
def decorator(argument):
def real_decorator(function):
def wrapper(*args):
for arg in args:
assert type(arg)==int,f'{arg} is not an interger'
result = function(*args)
result = result*argument
return result
return wrapper
return real_decorator
装饰器的使用
@decorator(2)
def adder(*args):
sum=0
for i in args:
sum+=i
return sum
然后
adder(2,3)
生产
10
but
adder('hi',3)
生产
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-143-242a8feb1cc4> in <module>
----> 1 adder('hi',3)
<ipython-input-140-d3420c248ebd> in wrapper(*args)
3 def wrapper(*args):
4 for arg in args:
----> 5 assert type(arg)==int,f'{arg} is not an interger'
6 result = function(*args)
7 result = result*argument
AssertionError: hi is not an interger
def decorator(argument):
def real_decorator(function):
def wrapper(*args):
for arg in args:
assert type(arg)==int,f'{arg} is not an interger'
result = function(*args)
result = result*argument
return result
return wrapper
return real_decorator
装饰器的使用
@decorator(2)
def adder(*args):
sum=0
for i in args:
sum+=i
return sum
然后
adder(2,3)
生产
10
but
adder('hi',3)
生产
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-143-242a8feb1cc4> in <module>
----> 1 adder('hi',3)
<ipython-input-140-d3420c248ebd> in wrapper(*args)
3 def wrapper(*args):
4 for arg in args:
----> 5 assert type(arg)==int,f'{arg} is not an interger'
6 result = function(*args)
7 result = result*argument
AssertionError: hi is not an interger
定义这个decoratorize函数来生成定制的decorator函数:
def decoratorize(FUN, **kw):
def foo(*args, **kws):
return FUN(*args, **kws, **kw)
return foo
可以这样用:
@decoratorize(FUN, arg1 = , arg2 = , ...)
def bar(...):
...
下面是一个使用带有参数的装饰器的Flask示例。假设我们有一个路由'/user/name',我们想要映射到他的主页。
def matchR(dirPath):
def decorator(func):
def wrapper(msg):
if dirPath[0:6] == '/user/':
print(f"User route '{dirPath}' match, calling func {func}")
name = dirPath[6:]
return func(msg2=name, msg3=msg)
else:
print(f"Input dirPath '{dirPath}' does not match route '/user/'")
return
return wrapper
return decorator
#@matchR('/Morgan_Hills')
@matchR('/user/Morgan_Hills')
def home(**kwMsgs):
for arg in kwMsgs:
if arg == 'msg2':
print(f"In home({arg}): Hello {kwMsgs[arg]}, welcome home!")
if arg == 'msg3':
print(f"In home({arg}): {kwMsgs[arg]}")
home('This is your profile rendered as in index.html.')
输出:
User route '/user/Morgan_Hills' match, calling func <function home at 0x000001DD5FDCD310>
In home(msg2): Hello Morgan_Hills, welcome home!
In home(msg3): This is your profile rendered as in index.html.
假设你有一个函数
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)
编写一个带参数和不带参数的装饰器是一个挑战,因为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
玩一下这段代码。
问题是用户必须提供键、值对的参数,而不是位置参数,并且第一个参数是保留的。