9

再帰呼び出しを含めて、再帰関数をラップするにはどうすればよいですか?たとえば、given fooand 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 was called"最初の呼び出しでのみ出力されます。再帰呼び出しは引き続きアドレスしますfoo()

モンキーパッチを当てたり、内部を突いたりしてもかまいません。このコードを次の核弾頭処理プログラムに追加する予定はないので、たとえそれが悪い考えであっても、その効果を達成したいと思います。

編集:たとえば、パッチを適用して機能foo.func_globalsをオーバーライドしますfoo.__name__か?それが常にある場合、私が気にかけるべき副作用はありますか?

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関数の結果を1回だけ呼び出していることが理由です。これをデコレータとして使用すると、モジュール名前空間の定義が実際に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 に答える