3

假设我有两个脚本:

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()ab

4

1 回答 1

1

这是一个非常有趣的问题。首先是一个快速的解决方法,您可以在调用时提供字典以用作本地和全局命名空间execfile(),使用空字典可以globals正常工作:

# test_fun1.py
a = 1

def test1():
    print a
    execfile('test_fun2.py', {})

test1()

或者,如果您希望代码在模块的全局范围内执行,您可以使用globals()而不是{}.

现在谈谈为什么这不起作用......来自以下文档execfile()

如果省略了两个字典,则表达式将在execfile()被调用的环境中执行。

这里的“两个字典”指的是可选的全局变量局部变量参数execfile()。在这种情况下,“被调用的环境”是test_fun1.pyexecfile()中函数的本地范围。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()修改默认本地人字典。如果您需要在函数返回后查看代码对局部变量的影响,请传递显式局部变量字典。不能可靠地用于修改函数的局部变量。execfile()execfile()

所以你有了它,这里有一个明确的警告,它execfile()不能用于可靠地修改函数的局部变量,而这正是这段代码试图做的。b = 2and语句在的def print_a(): ...范围内执行test1(),但它们实际上并没有成功地将这些名称添加到命名空间,因此稍后尝试访问这些名称会失败。

于 2013-08-13T19:06:39.440 回答