Python:包装递归函数

时间:2012-05-13 18:37:26

标签: python higher-order-functions

如何包装递归函数,包括递归调用?例如,给定foowrap

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 was called"。递归调用仍然会解决foo()

我不介意猴子修补,或在内部戳。我不打算将这个代码添加到下一个核弹头处理程序中,所以即使这是一个坏主意,我也希望达到这个效果。

修改:例如,是否会修补foo.func_globals以覆盖foo.__name__工作?如果它总是这样,我应该注意任何副作用吗?

2 个答案:

答案 0 :(得分:10)

如果你使用你的包装函数作为装饰器,它就可以工作。

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的定义,因此它的内部调用解析为包装版本。

答案 1 :(得分:0)

用类而不是函数包装函数:

>>> 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