简体   繁体   English

Python:包装递归函数

[英]Python: wrapping recursive functions

How can I wrap a recursive function, recursive calls included? 如何包装递归函数,包括递归调用? For example, given foo and wrap : 例如,给定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) will only output "f was called" with the first call. wrap(foo)(x)只会在第一次调用时输出"f was called" Recursive calls still address foo() . 递归调用仍然解决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? 编辑 :例如,修补foo.func_globals以覆盖foo.__name__工作? If it always does, any side-effects I should be minding? 如果它总是这样,我应该注意任何副作用?

It works if you use your wrapper function 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

Reason being that in your example, you're only calling the result of the wrap function once. 原因是在您的示例中,您只调用一次wrap函数的结果。 If you use it as a decorator it actually replaces the definition of foo in the module namespace with the decorated function, so its internal call resolves to the wrapped version. 如果您将它用作装饰器,它实际上将模块命名空间中的foo定义替换为装饰函数,因此其内部调用将解析为包装版本。

Wrap the function with a class, rather than 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM