7

次のような関数デコレータを作成しました。

def tsfunc(func):
    def wrappedFunc():
        print '%s() called' % func.__name__
        return func()
    return wrappedFunc()

@tsfunc
def foo():
    pass

foo()  # to get it work, use foo instead of foo()
foo()

次のエラー メッセージが表示されました。

foo() called
Traceback (most recent call last):
  File "decorator.py", line 11, in <module>
    foo()
TypeError: 'NoneType' object is not callable

「foo()」を「foo」に置き換えることで機能します。しかし、私はまだ期待した結果を得られませんでした:

foo() called

foo関数は一度しか呼び出されないようです。

なぜこれが起こっているのかを理解するのを手伝ってください。

4

4 に答える 4

18

結果ではなく、ラッパー関数自体を返す必要があります。

def tsfunc(func):
    def wrappedFunc():
        print '%s() called' % func.__name__
        return func()
    return wrappedFunc   # Do not call the function, return a reference instead

デコレーターは、装飾されたアイテムをデコレーターの戻り値に置き換えます。

@tsfunc
def foo():
    # ....

次と同等です。

def foo():
    # ....
foo = tsfunc(foo)

これは(コード内で)次のように展開されます。

foo = wrappedFunc()

そのため、関数をそれ自体ではなく、呼び出しfooの結果に置き換えていました。wrappedFunc()wrappedFunc

于 2013-01-26T10:55:27.217 に答える
3

の括弧を削除する必要があります

return wrappedFunc

デコレーターは、ラッパー関数を呼び出すのではなく、返すことになっています。

この修正により、コードは以下を生成します。

foo() called
foo() called
于 2013-01-26T10:56:06.073 に答える