Python:在循环中包装函数
在Python中,在循环中包装多个函数的正确方法是什么? 我有通用包装器和函数列表。我需要将列表中的所有函数包装到一个循环中,但是对于funcs中的f:对我不起作用。 执行此操作的正确方法是什么Python:在循环中包装函数,python,function,wrapper,decorator,Python,Function,Wrapper,Decorator,在Python中,在循环中包装多个函数的正确方法是什么? 我有通用包装器和函数列表。我需要将列表中的所有函数包装到一个循环中,但是对于funcs中的f:对我不起作用。 执行此操作的正确方法是什么 def orig_func1(x, y): print "x=%i y=%i" % (x,y) def orig_func2(a, b): print "a=%i b=%i" % (a,b) def wrapper(func): f_name = func.__name__
def orig_func1(x, y):
print "x=%i y=%i" % (x,y)
def orig_func2(a, b):
print "a=%i b=%i" % (a,b)
def wrapper(func):
f_name = func.__name__
print 'adding hook for function [%s]' % f_name
def inner(*args, **kwargs):
print 'I am before original function'
ret = func(*args, **kwargs)
print 'I am after original function'
return ret
return inner
funcs = [orig_func1, orig_func2]
print funcs
for f in funcs:
f = wrapper(f)
print funcs
结果显示列表中的函数没有更改:
[<function orig_func1 at 0x022F78F0>, <function orig_func2 at 0x022F7930>]
adding hook for function [orig_func1]
adding hook for function [orig_func2]
[<function orig_func1 at 0x022F78F0>, <function orig_func2 at 0x022F7930>]
x=1 y=2
a=3 b=4
[,]
为函数[orig_func1]添加钩子
为函数[orig_func2]添加钩子
[, ]
x=1 y=2
a=3 b=4
在该循环中,f
只不过是一个局部变量。除非直接修改列表,否则不会更改任何有意义的内容。而不是:
for f in funcs:
f = wrapper(f)
您应该这样做:
for i, f in enumerate(funcs):
funcs[i] = wrapper(f)
这会将列表中的函数更改为可以使用的新的包装函数。但它仍然不会改变函数的最终定义。一旦定义完成,除了完整的重新定义或在函数定义上方使用的包装器之外,任何东西都无法实现;直接调用
orig_func1
将在for
循环前后获得相同的结果。如果您想在运行时修改函数,您必须不断引用刚刚创建的函数的此包装版本。您应该使用。它们是修改函数行为的正确方法,而不是当前的循环方法。如果官方文件没有说得够清楚的话,还有一些教程对我帮助很大
您现有的代码实际上看起来很像我的第一个教程链接中的一些代码片段。您应该使用@decorator
语法替换循环,而不是手动换行
也就是说,你可以通过理解来完成你最初的意图。将您的循环替换为以下内容:
funcs = [wrapper(func) for func in funcs]
其他评论和回答是正确的,您在循环中对f的修改不起作用,因为它在该循环中有一个局部范围,并且没有修改您的列表。我使用以下方法实现了所需的行为:
import Module1, Module2
funcs = ['Module1.func1','Module1.func2','Module2.func1','Module2.func2']
hooks = {}
def wrapper(func,f_name):
if not hooks.has_key(f_name):
hooks[f_name] = {'before':[],
'after':[]}
def inner(*args, **kwargs):
for f in hooks[f_name]['before']:
f(*args, **kwargs)
ret = func(*args, **kwargs)
for f in hooks[f_name]['after']:
f(*args, **kwargs)
return ret
return inner
def implementHooks():
for f in funcs:
obj_name, func_name = f.rsplit('.',1)
obj = globals()[obj_name]
func = getattr(obj, func_name)
setattr(obj, func_name, wrapper(func, f))
implementHooks()
def module1_func1_hook():
print 'Before running module1.func1()'
hooks['Module1.func1']['before'] += [module1_func1_hook]
在该循环中,
f
只是一个局部变量。除非直接修改列表,否则您不会更改任何有意义的内容。您到底想做什么?或者,funcs=map(wrapper,funcs)