我正在尝试使用 exec 运行一段 python 代码。
my_code = """
class A(object):
pass
print 'locals: %s' % locals()
print 'A: %s' % A
class B(object):
a_ref = A
"""
global_env = {}
local_env = {}
my_code_AST = compile(my_code, "My Code", "exec")
exec(my_code_AST, global_env, local_env)
print local_env
这会产生以下输出
locals: {'A': <class 'A'>}
A: <class 'A'>
Traceback (most recent call last):
File "python_test.py", line 16, in <module>
exec(my_code_AST, global_env, local_env)
File "My Code", line 8, in <module>
File "My Code", line 9, in B
NameError: name 'A' is not defined
但是,如果我将代码更改为这样 -
my_code = """
class A(object):
pass
print 'locals: %s' % locals()
print 'A: %s' % A
class B(A):
pass
"""
global_env = {}
local_env = {}
my_code_AST = compile(my_code, "My Code", "exec")
exec(my_code_AST, global_env, local_env)
print local_env
然后它工作正常 - 给出以下输出 -
locals: {'A': <class 'A'>}
A: <class 'A'>
{'A': <class 'A'>, 'B': <class 'B'>}
显然 A 存在且可访问 - 第一段代码出了什么问题?我正在使用 2.6.5,干杯,
Colin
* 更新 1 *
如果我检查类内的 locals() -
my_code = """
class A(object):
pass
print 'locals: %s' % locals()
print 'A: %s' % A
class B(object):
print locals()
a_ref = A
"""
global_env = {}
local_env = {}
my_code_AST = compile(my_code, "My Code", "exec")
exec(my_code_AST, global_env, local_env)
print local_env
然后很明显 locals() 在两个地方是不一样的 -
locals: {'A': <class 'A'>}
A: <class 'A'>
{'__module__': '__builtin__'}
Traceback (most recent call last):
File "python_test.py", line 16, in <module>
exec(my_code_AST, global_env, local_env)
File "My Code", line 8, in <module>
File "My Code", line 10, in B
NameError: name 'A' is not defined
不过,如果我这样做的话,就没有问题了——
def f():
class A(object):
pass
class B(object):
a_ref = A
f()
print 'Finished OK'
*更新2*
好的,这里的文档 -http://docs.python.org/reference/executionmodel.html
'类定义是可以使用和定义名称的可执行语句。这些引用遵循名称解析的正常规则。类定义的命名空间成为类的属性字典。在类范围内定义的名称在方法中不可见。'
在我看来,“A”应该在作为 B 定义的可执行语句中作为自由变量使用,当我们调用上面的 f() 时会发生这种情况,但当我们使用 exec() 时不会发生这种情况。这可以通过以下更容易地显示 -
my_code = """
class A(object):
pass
print 'locals in body: %s' % locals()
print 'A: %s' % A
def f():
print 'A in f: %s' % A
f()
class B(object):
a_ref = A
"""
哪个输出
locals in body: {'A': <class 'A'>}
A: <class 'A'>
Traceback (most recent call last):
File "python_test.py", line 20, in <module>
exec(my_code_AST, global_env, local_env)
File "My Code", line 11, in <module>
File "My Code", line 9, in f
NameError: global name 'A' is not defined
所以我想新的问题是 - 为什么这些局部变量没有在函数和类定义中作为自由变量公开 - 这似乎是一个非常标准的闭包场景。