compile()如何在python中工作?

时间:2011-09-27 03:46:49

标签: python

我有两个代码让我很困惑。

def get_context():
    __gc = globals()
    __lc = locals()

    def precompiler(code):
        exec code in __lc

    def compiler(script, scope):
        return compile(script, scope, 'eval')

    def executor(expr):
        return eval(expr, __gc, __lc)

    return precompiler, compiler, executor

maker1, compiler1, executor1 = get_context()
maker2, compiler2, executor2 = get_context()

maker1("abc = 123")
maker2("abc = 345")
expr1 = compiler1("abc == 123", "test.py")
print "executor1(abc == 123):", executor1(expr1)
print "executor2(abc == 123):", executor2(expr1)

结果是:
executor1(abc == 123):真实 executor2(abc == 123):False

为什么编译只在闭包中执行一次,字节码可以在两者中运行?

此处还有另一个代码:

def get_context():
    __gc = globals()
    __lc = locals()

    test_var = 123

    def compiler(script, scope):
        return compile(script, scope, 'eval')

    def executor(expr):
        return eval(expr, __gc, __lc)

    return compiler, executor


compiler1, executor1 = get_context()
compiler2, executor2 = get_context()

expr1 = compiler1("test_var == 123", "test.py")
print "executor1(test_var == 123):", executor1(expr1)
print "executor2(test_var == 123):", executor2(expr1)

结果是:
NameError:名称'test_var'未定义为

这是怎么发生的?

为什么编译需要检查闭包的环境(变量或其他一些),而不依赖于闭包?这就是我的困惑!

2 个答案:

答案 0 :(得分:1)

在第一个示例中,您在第一个上下文中执行'abc = 123',在第二个上下文中执行'abc = 345'。因此,'test_var == 123'在您的第一个上下文中为true,在第二个上下文中为false。

在您的第二个示例中,您发现了一个有趣的情况,即解释器已从上下文中删除了test_var,因为未引用test_var。

答案 1 :(得分:1)

对于你的第一个问题,compile只需要获取python代码并生成字节码。它不会以任何方式依赖于编译它的闭包。如果你产生了一个字符串,它就没那么不同了。该字符串不是永久地与创建它的函数绑定在一起,也不是代码对象。

对于第二个问题,locals()在调用局部变量时会构建一个字典。由于您在调用locals之后设置了test_var,因此它没有它。如果你想在本地人中使用test_var,你需要在之后调用它。