请考虑以下简化示例:
permitted = True
class is_allowed(object):
def __init__(self, some_arg):
# this is actually needed in the complete code
self.some_arg = some_arg
def __call__(self, f):
if permitted == False:
raise Exception("not authenticated to do that")
def wrapped_f(*args, **kwargs):
f(*args, **kwargs)
return wrapped_f
@is_allowed("blah")
def print_hi():
print("hi")
print_hi()
permitted = False
print_hi()
我想问题是装饰器只在定义函数print_hi()时被调用一次.因此,全局变量的变化无效.有没有办法绕过这种行为?
解决方法:
移动wrapped_f内部的检查
def __call__(self, f):
def wrapped_f(*args, **kwargs):
if not permitted:
raise Exception("not authenticated to do that")
f(*args, **kwargs)
return wrapped_f
在wrapped_f之外,在创建函数时检查它.在内部,它成为新callable的主体的一部分,这意味着每次有呼叫时都会检查它.
您想要意识到将调用wrapped_f而不是print_hi,因此您希望应该包含在函数中的任何行为都在其中.