我想使用内置的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
但是在'globals'参数中定义了y
,它确实有效:
>>> x = eval('lambda: print(y)', {'y': 2},{})
>>> x()
2
据我所知,lambda表达式应该捕获整个当前帧,包括globals和locals参数中定义的所有变量。
那么为什么Python的行为如此?
答案 0 :(得分:0)
x = eval('lambda: print(y)',{},{'y':2})
在第一部分更改参数顺序中不等于此行x = eval('lambda: print(y)', {'y': 2},{})
,它应该可以正常工作
答案 1 :(得分:0)
非常简单:传递一个填充的locals
目录并不会改变python解析函数代码的方式,并决定哪些名称是本地名称,哪些名称是全局名称。
本地名称是在函数体内绑定的参数名称和名称,而不是明确声明的全局变量或非本地变量。这里,y
不是一个参数,并且没有绑定在函数体内(无论如何都不可能在lambda
中),所以它被编译器标记为全局。
现在那些全局和本地环境是那些用来评估表达式本身的环境(这里是完整的&#39; lambda:print(y)&#39;表达式),而不是&#34; lambda的本地环境&# 39; s body&#34 ;,所以即使有办法让y
本地的功能部门(提示:那里有一个 - 但它不会解决你的问题问题)这个名字仍然不会自动地#34;设置为&#39; y&#39;传递给eval
的当地人dict中的值。
但这实际上不是问题 - 由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()
是非常危险的,而且往往是更好的解决方案,这取决于你的确切问题&# 39;重新尝试解决。你没有提供任何上下文,所以不可能多说,但我不得不说我实际上很难想到f = eval("lambda: whatever")
之类的具体用例。