Python 为什么eval函数中的lambda可以';t在用户定义的';当地人';字典

Python 为什么eval函数中的lambda可以';t在用户定义的';当地人';字典,python,lambda,eval,Python,Lambda,Eval,我想使用内置的eval函数计算lambda表达式,并在“locals”参数中定义变量y。遗憾的是,结果函数不起作用: >>>x = eval('lambda: print(y)',{},{'y':2}) >>>x() Traceback (most recent call last): File "<pyshell#75>", line 1, in <module> x() File "<string>",

我想使用内置的
eval
函数计算lambda表达式,并在“locals”参数中定义变量
y
。遗憾的是,结果函数不起作用:

>>>x = eval('lambda: print(y)',{},{'y':2})
>>>x()
Traceback (most recent call last):
  File "<pyshell#75>", line 1, in <module>
    x()
  File "<string>", line 1, in <lambda>
NameError: name 'y' is not defined
据我所知,lambda表达式应该捕获整个当前帧,包括globals和locals参数中定义的所有变量


那么为什么Python的行为是这样的呢?

x=eval('lambda:print(y),{},{'y':2})不等于这一行
x=eval('lambda:print(y),{'y':2})
在第一部分中,更改参数顺序,它应该很简单:传递一个填充的
locals
目录不会改变python解析函数代码的方式,并决定哪些名称是局部名称,哪些名称是全局名称

局部名称是参数名称和绑定在函数体中的名称,不是显式声明的全局或非局部名称。这里,
y
不是一个参数,并且没有绑定在函数体中(这在
lambda
中无论如何都是不可能的),因此编译器将其标记为全局的

现在,这些全局和局部环境是用于计算表达式本身的环境(这里是完整的“lambda:print(y)”表达式),而不是“lambda主体的局部环境”,因此,即使有一种方法可以使
y
成为函数主体的局部环境(提示:有一种-但它不会解决您的问题)此名称仍不会“自动”设置为传递给
eval
的本地指令中的“y”值

但这实际上不是问题-由
eval(“lambda:y”,{“y”:42})创建的函数捕获传递给
eval
的全局dict,并使用它代替模块/脚本/任何全局,因此它将按预期工作:

Python 3.4.3 (default, Nov 28 2017, 16:41:13) 
[GCC 4.8.4] on linux
>>> f = eval("lambda: y+2", {'y':2}, {})
>>> f()
4
>>> y = 42
>>> f()
4

现在你有了解释,我想补充一点,那就是
eval()
是非常危险的
,而且通常有更好的解决方案,这取决于你试图解决的确切问题。您没有提供任何上下文,因此不可能讲得更多,但我必须说,我实际上很难为
f=eval(“lambda:whatever”)

这样的事情思考具体的用例,您知道
eval
的危险吗?
Python 3.4.3 (default, Nov 28 2017, 16:41:13) 
[GCC 4.8.4] on linux
>>> f = eval("lambda: y+2", {'y':2}, {})
>>> f()
4
>>> y = 42
>>> f()
4