假设我有两个脚本:
test_fun1.py
a = 1
def test1():
print a
execfile('test_fun2.py')
test1()
test_fun2.py
b = 2
def print_a():
print 'a'
def test2():
print_a()
print b
test2()
当我运行test_fun1.py
时,我收到此错误:
NameError: global name 'print_a' is not defined
如果我排除print_a()
test2()
a
,则会同时打印b
和{{1}}。为什么将变量设置为全局但函数不会?
答案 0 :(得分:1)
这是一个非常有趣的问题。首先是一个快速的解决方法,您可以在调用execfile()
时提供用作本地和全局命名空间的词典,使用globals
的空字典可以正常工作:
# test_fun1.py
a = 1
def test1():
print a
execfile('test_fun2.py', {})
test1()
或者,如果您希望代码在模块的全局范围内执行,则可以使用globals()
代替{}
。
现在问及为什么这不起作用......来自execfile()
的文档:
如果省略两个词典,则表达式在调用
execfile()
的环境中执行。
此处“两个词典”指的是execfile()
的可选全局和本地参数。在这种情况下,“调用execfile()
的环境”是test_fun1.py中函数test1()
的本地范围。现在仍然期望这样做是合理的,因为看起来它应该做的事情基本上等同于以下内容:
a = 1
def test1():
print a
# code executed by execfile
b = 2
def print_a():
print 'a'
def test2():
print_a()
print b
test2()
test1()
然而,文档中稍后会有一条说明:
注意:默认 locals 的行为与下面的函数
locals()
相同:对默认 locals 字典的修改不应该是尝试。如果您需要在函数execfile()
返回后查看代码对 locals 的影响,请传递显式的 locals 字典。execfile()
无法可靠地用于修改函数的本地人。
所以你有它,这里有一个明确的警告,execfile()
不能用于可靠地修改函数的本地,这正是这段代码试图做的事情。 b = 2
和def print_a(): ...
语句在test1()
的范围内执行,但它们实际上并没有成功地将这些名称添加到命名空间,因此稍后尝试访问这些名称失败。