Exec,闭包和范围

时间:2013-11-22 22:45:38

标签: python scope closures

假设我想用exec实现一个身份装饰器(也就是说,它不应该对没有参数的函数做任何事情)。当我尝试使用该装饰器定义一个闭包时,该范围在f_factory函数的末尾存活并改变接下来的内容。

我想了解为什么最后一次打印返回“1b”而不是“1”

def exec_identity(f):

    gl = globals()
    gl.update({'f':f})

    exec "def idfun(): return f()" in gl, locals()
    return idfun


class CallableClass(object):
    def __init__(self, s):
        self.s = s

    def make_callable(self):
        def f_factory(s):
            def f():
                print s

            return exec_identity(f)
            #return f
        return f_factory(self.s)




c1 = CallableClass("1")
f1 = c1.make_callable()
f1()
c1.s = "1b"
f1()
f1b = c1.make_callable()
f1b()
f1()

"""
Result:

1
1
1b
1b
"""

我知道如果我可以保留这样的exec语句,以使其按预期工作:

exec "def idfun(): return f()" in {'f':f}, locals()

1 个答案:

答案 0 :(得分:2)

这与

的事实有关
gl = globals()
gl.update({'f':f})

在所有情况下都适用于同一个对象。

所以全局f()与新的gl = dict(globals()) gl.update({'f':f}) 交换,并被调用。旧的,随着它的关闭,迷失了。

globals()

通过复制{{1}}词典来阻止这种情况。