1

関数名から関数へのマッピングを含む python ハッシュがあります。関連する関数を呼び出すように各ハッシュ エントリを変更したいのですが、最終的なカスタム関数も呼び出すようにします。出口フックのように振る舞うことです。

def original():
    print "original work"

になる

def replacement():
    original()
    print "notify somebody..."

私の問題は、次のコードの出力が期待どおりではないため、スコープなどを間違っていると思います。多分私が尋ねることができれば、これを行うためのより良い方法はありますか? 元のcbの変更に固執したいのは、サードパーティのコードであり、変更する場所が少ないほど良いからです。

#!/usr/bin/python 

def a():
    print "a"

def b():
    print "b"

def c():
    print "c"


orig_fxn_cb = dict()

" basic name to function callback hash "
orig_fxn_cb['a'] = a
orig_fxn_cb['b'] = b
orig_fxn_cb['c'] = c

" for each call back routine in the hash append a final action to it "
def appendFxn(fxn_cb):
    appended_fxn_cb_new = dict()
    for i in orig_fxn_cb.keys():
        cb = fxn_cb[i]
        def fxn_tail():
            cb()
            print cb.__name__, "tail" 

        appended_fxn_cb_new[i] = fxn_tail
        appended_fxn_cb_new[i]()
    return appended_fxn_cb_new

" make up a modified callback hash "
xxx = appendFxn(orig_fxn_cb)
print xxx

for i in xxx:
    print xxx[i]()
4

3 に答える 3

4

あなたは後ですか:

from functools import wraps

def notifier(f):
    @wraps(f)
    def wrapped(*args, **kwargs)
        res = f(*args, **kwargs)
        print "notify somebody..."
        return res
    return wrapped

@notifier
def original():
    print "original work"

# or: original = notifier(original)

original()
original work
notify somebody...
于 2012-11-20T23:53:24.250 に答える
2

実行している問題は、関数cbで使用している変数に関係していますappendFxn。内部関数定義は名前でこの値にアクセスするため、それらはすべて同じ内部コールバック関数への参照を持つことになります (反復で最後に出現した関数)。

これは、ラッパー関数のデフォルト引数で修正できます。

def appendFxn(fxn_cb):
    appended_fxn_cb_new = dict()
    for i in orig_fxn_cb.keys():
        cb = fxn_cb[i]
        def fxn_tail(cb = cb):           # fix is here!
            cb()
            print cb.__name__, "tail" 

        appended_fxn_cb_new[i] = fxn_tail
        appended_fxn_cb_new[i]()
    return appended_fxn_cb_new

デフォルトの引数を使用すると、現在の値が内部関数内cbの名前にバインドされます。cbそうすれば、元のcb変数が新しい値に設定されても、既存の関数は古い値を保持します。(必要に応じて、関数の引数を作成し、外部変数cb = fxn_cb[i]を取り除くこともできます。)cb

于 2012-11-21T00:02:18.973 に答える
0

期待される出力が何であるかわかりませんが、ここではうまくいくようです。辞書内のすべての関数を、元の関数を呼び出して元の名前と "tail" を出力するコピーに置き換えます。関数を置き換えると、それらも実行されます。最後に、結果の辞書を繰り返し処理し、再度実行します。

appendFxn を何度も呼び出すと予期しない動作が発生する可能性があるのは、次のfor i in orig_fxn_cb.keys():行です。orig_fxn_cb渡されたパラメーターの代わりにグローバルを参照するfxn_cbため、それ以上呼び出してもマップ内の関数は変更されません。

于 2012-11-20T23:54:11.227 に答える