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

我不知道预期的输出是什么,它似乎在这里工作正常。它将字典中的所有函数替换为调用原始函数的副本,然后打印原始名称和“尾巴”。当它替换函数时,它也执行它们。最后,您遍历生成的字典并再次执行它们。

如果您多次调用 appendFxn 可能会给您带来意想不到的行为for i in orig_fxn_cb.keys():。它引用全局orig_fxn_cb而不是fxn_cb传递的参数,因此进一步调用不会更改映射中的函数。

于 2012-11-20T23:54:11.227 回答