6

私はこのスコープの振る舞いについて混乱しています:

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が、ループの反復ごとに再定義すると、最後のインスタンスが属性に保存されます。func_wrapper = None私も下に追加しようとしましたsetattrが、それは役に立ちません(私も不思議に思ったでしょう...)。

私は盲目ですか?これを回避/修正する方法すらわかりません。

4

1 に答える 1

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にアクセスします。これは、ループの実行ごとに変更されます。修正された例では、これは防止されています。

于 2012-06-22T22:33:22.007 に答える