Python:包装递归函数
如何包装递归函数,包括递归调用?例如,给定Python:包装递归函数,python,higher-order-functions,Python,Higher Order Functions,如何包装递归函数,包括递归调用?例如,给定foo和wrap: def foo(x): return foo(x - 1) if x > 0 else 1 def wrap(f): def wrapped(*args, **kwargs): print "f was called" return f(*args, **kwargs) return wrapped wrap(foo)(x)只会在第一次调用时输出“f被调用”。递归调用
foo
和wrap
:
def foo(x):
return foo(x - 1) if x > 0 else 1
def wrap(f):
def wrapped(*args, **kwargs):
print "f was called"
return f(*args, **kwargs)
return wrapped
wrap(foo)(x)
只会在第一次调用时输出“f被调用”
。递归调用仍然是地址foo()
我不介意猴子打补丁,或者在内部乱摸。我不打算在下一个核弹头处理程序中添加此代码,所以即使这是一个坏主意,我也希望达到效果
Edit:例如,通过修补
foo.func\u globals
覆盖foo.\uu name\uuuu
是否有效?如果总是这样,我应该注意的副作用是什么?如果您将包装器函数用作装饰器,它会起作用
def wrap(f):
def wrapped(*args, **kwargs):
print "f was called"
return f(*args, **kwargs)
return wrapped
@wrap
def foo(x):
return foo(x - 1) if x > 0 else 1
原因是在您的示例中,您只调用一次
wrap
函数的结果。如果将其用作装饰器,它实际上会用装饰函数替换模块命名空间中的foo
定义,因此其内部调用解析为包装版本。用类而不是函数包装函数:
>>> def foo(x):
... return foo(x-1) if x > 0 else 1
...
>>> class Wrap(object):
... def __init__(self, f): self.f = f
... def __call__(self, *args, **kwargs):
... print "f called"
... return self.f(*args, **kwargs)
...
>>> foo = Wrap(foo)
>>> foo(4)
f called
1
为什么我没想到呢?哈哈!好极了谢谢。事实上,在您最初的示例中,如果您使用foo=wrap(foo),然后调用foo(5),它也会做同样的事情:)但是decorator语法是更清晰的方法。这会起作用,但是有没有一种方法可以在不覆盖命名空间中的原始名称的情况下完成它@brandizzi没有忘记,在接受之前有一个最短的时间:)不,如果不覆盖名称空间中的原始名称,就无法完成。您正在按名称调用函数;若要使用该名称调用wrap函数而不是原始函数,wrap函数必须替换命名空间中的原始函数。@kindall实际上,可以通过向
foo
明确传递包装来完成。但是这个!那正是我不想要的!xDIt不需要将函数包装到类中-函数装饰器也可以工作。它在OP示例中不起作用,因为应该将包装的函数绑定到原始名称,如@Kamil answer中所示。我以为您希望包装器函数只执行一次:P.是的,Kamil的答案很好地解决了这个问题。