奇怪的Python函数范围行为

时间:2012-06-22 22:26:07

标签: python

我对此范围行为感到困惑:

class Bar:
    def __init__(self):
        for fn in ["open","openW","remove","mkdir","exists","isdir","listdir"]:
            print "register", fn
            def func_wrapper(filename):
                print "called func wrapper", fn, filename
            setattr(self, fn, func_wrapper)

bar = Bar()
bar.open("a")
bar.remove("b")
bar.listdir("c")

这给出了输出:

register open
register openW
register remove
register mkdir
register exists
register isdir
register listdir
called func wrapper listdir a
called func wrapper listdir b
called func wrapper listdir c

但我希望func_wrapper始终是正确的功能。我知道func_wrapper的范围是整个函数,但我在每次循环迭代中重新定义它,最后一个实例在attrib中被保存。我还尝试在func_wrapper = None下面添加setattr,但这没有帮助(也会让我感到奇怪......)。

我是瞎了吗?我甚至不知道如何解决/解决这个问题。

1 个答案:

答案 0 :(得分:6)

使用

class Bar:
    def __init__(self):
        for fn in ["open","openW","remove","mkdir","exists","isdir","listdir"]:
            print "register", fn
            def func_wrapper(filename, fn=fn):
                print "called func wrapper", fn, filename
            setattr(self, fn, func_wrapper)

或更强大,

def mkwrapper(fn):
    def func_wrapper(filename):
        print "called func wrapper", fn, filename
    func_wrapper.__name__ = fn
    return func_wrapper

class Bar:
    def __init__(self):
        for fn in ["open","openW","remove","mkdir","exists","isdir","listdir"]:
            print "register", fn
            func_wrapper = mkwrapper(fn)
            setattr(self, fn, func_wrapper)

在您的原始示例中,所有生成的函数都访问相同的外部变量fn,该变量在每次循环运行中都会发生变化。在更正的示例中,这是可以防止的。