猿问

为什么 eval 找不到定义在外部函数中的变量?

我知道使用eval()通常意味着糟糕的代码,但我eval()在内部函数中偶然发现了一个我无法理解的函数的奇怪行为。如果我们写:


def f(a):

    def g():

        print(eval('a'))

    return g()

f(1)在这种情况下运行会产生NameError,声称a未定义。但是,如果我们定义


def f(a):

    def g():

        b = a + 1

        print(eval('a'))

    return g()

然后运行f(1)打印1。


局部和全局变量发生了一些我不太明白的事情。是a只在一个局部变量g(),当它被“拿来主义”的东西?这里发生了什么?


拉莫斯之舞
浏览 485回答 2
2回答

慕少森

简而言之,由于eval是动态评估,解释器无法知道它应该添加a到g. 为了效率,解释器不会将不需要的变量添加到dict局部变量中。来自文档eval:表达式参数被解析和评估为 Python 表达式(从技术上讲,条件列表),使用 globals 和 locals 字典作为全局和本地命名空间。这意味着这些函数eval(expression)将globals()用作其默认全局范围,locals()如果没有提供,则用作其局部范围。虽然,在你的第一个例子a中都不是。def f(a):    print("f's locals:", locals())    def g():        print("g's locals:", locals())        print(eval('a'))    return g()f(1)实际上,由于解释器a在解析 的主体时看不到对 的引用g,因此不会将其添加到其局部变量中。要使其正常工作,您需要nonlocal a在g.输出f's locals: {'a': 1}g's locals: {}Traceback ......NameError: name 'a' is not defined在您的第二个示例中,a在g局部变量中,因为它在作用域中使用。def f(a):    print("f's locals:", locals())    def g():        print("g's locals:", locals())        b = a + 1        print("g's locals after b = a + 1:", locals())        print(eval('a'))    return g()f(1)输出f's locals: {'a': 1}g's locals: {'a': 1}g's locals after b = a + 1: {'a': 1, 'b': 2}1

呼啦一阵风

看起来 eval() 只能在 local(here,g) 或 global 中查找变量,而不能在其父环境(此处为 f)中查找变量。四处走走是将变量设置为全局。 定义 f(a):         global b #注意,不能直接使用"global a",会报错:"name 'a' is parameter and global"     b=a     定义 g():         打印(评估('b'))     返回 g()f(1)输出:1
随时随地看视频慕课网APP

相关分类

Python
我要回答