9

How can I wrap a recursive function, recursive calls included? For example, given foo and 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) will only output "f was called" with the first call. Recursive calls still address foo().

I don't mind monkey patching, or poking around internals. I'm not planning to add this code to the next nuclear warhead handling program, so even if it's a bad idea, I'd like to achieve the effect.

Edit: for example, would patching foo.func_globals to override foo.__name__ work? If it always does, any side-effects I should be minding?

4

2 回答 2

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模块命名空间中的定义替换为装饰函数,因此其内部调用解析为包装版本。

于 2012-05-13T18:45:52.487 回答
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
于 2012-05-13T18:48:50.873 回答