我有两个代码让我很困惑。
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'未定义为
这是怎么发生的?
为什么编译需要检查闭包的环境(变量或其他一些),而不依赖于闭包?这就是我的困惑!
答案 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,你需要在之后调用它。