Using a decorator to bring variables into decorated function namespace
假设我有一个像这样的函数:
1 2 | def func(arg1, arg2): return arg1 + arg2 + arg3 |
我想引入
我试过这样做,这里建议我可以把论点传递给装饰师:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from functools import wraps def addarg(arg): def decorate(func): arg3 = arg @wraps(func) def wrapped(*args): return func(*args) return wrapped return decorate @addarg(3) def func(arg1, arg2): return arg1 + arg2 + arg3 if __name__ =="__main__": print(func(1, 2)) |
但我得到了这个错误(可以理解):
1 2 3 4 5 6 7 8 | Traceback (most recent call last): File"C:/Users/pbreach/Dropbox/FIDS/PhD/Code/anemi3/utils.py", line 19, in <module> print(func(1, 2)) File"C:/Users/pbreach/Dropbox/FIDS/PhD/Code/anemi3/utils.py", line 9, in wrapped return func(*args) File"C:/Users/pbreach/Dropbox/FIDS/PhD/Code/anemi3/utils.py", line 16, in func return arg1 + arg2 + arg3 NameError: name 'arg3' is not defined |
对于我的应用程序来说,能够用这种方式定义函数会更好。还有其他的方法,但随后必须向每个函数的主体添加更多的代码。
这有点老生常谈,但这种装饰的实现似乎可以满足您的需要。必须使
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | from functools import wraps def addarg(arg): def decorate(func): @wraps(func) def wrapped(*args): global_vars, local_vars = {'func': func, 'args': args}, {} func.__globals__.update(arg3=arg) exec('_result = func(*args)', global_vars, local_vars) return local_vars['_result'] return wrapped return decorate @addarg(3) def func(arg1, arg2): return arg1 + arg2 + arg3 if __name__ =="__main__": print(func(1, 2)) # -> 6 |
你可以那样做
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from functools import wraps def addarg(arg): def decorate(func): @wraps(func) def wrapped(*args): return func(*args, arg) return wrapped return decorate @addarg(3) def func(arg1, arg2, *args): return arg1 + arg2 + sum(args) if __name__ =="__main__": print(func(1, 2)) |
这样,您就不会附加到任何名称上,并且可以根据需要应用任意多的装饰器。所以,如果你想增加更多的装饰,它会起作用。例如
1 2 3 4 5 6 7 8 9 10 | @addarg(3) @addarg(3) @addarg(3) def func(arg1, arg2, *args): return arg1 + arg2 + sum(args) if __name__ =="__main__": print(func(1, 2)) # Output would be 12(1 + 2 + 3 + 3 + 3) |