Python: wrapping recursive functions

How can I wrap a recursive function, including recursive calls? 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" on the first call. Recursive calls are still addressed to foo() .

I do not mind monkey patches or shaking around internal organs. I do not plan to add this code to the next nuclear warhead processing program, so even if this is a bad idea, I would like to achieve an effect.

Edit : for example, fix foo.func_globals to override foo.__name__ ? If this is always the case, are there any side effects that I should remember?

+7
source share
2 answers

It works if you use your wrapper as a decorator.

 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 

The reason is that in your example, you only call the result of the wrap function once. If you use it as a decorator, it actually replaces the definition of foo in the module namespace with a decorated function, so its internal call is allowed for the wrapped version.

+9
source

Wrap a function with a class, not a function:

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

All Articles