为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

拉莫斯之舞 2021-06-12 18:08:14
我知道使用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(),当它被“拿来主义”的东西?这里发生了什么?
查看完整描述

2 回答

?
慕少森

TA贡献2019条经验 获得超9个赞

简而言之,由于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


查看完整回答
反对 回复 2021-06-16
?
呼啦一阵风

TA贡献1802条经验 获得超6个赞

看起来 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


查看完整回答
反对 回复 2021-06-16
  • 2 回答
  • 0 关注
  • 482 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信