在以下代码中,对 iszero
的第一个引用成功,但第二个(在 lambda 内部)给出了 NameError: 'iszero' is not defined
。
myblock = """
def iszero(x):
return x == 0
print(iszero(0)) #works
args = [0, 1, 2]
flts = list(filter(lambda f:(not iszero(f)), args)) #NameError
"""
mylocals = {}
exec(myblock, globals(), mylocals)
最佳答案
我将其归类为 Python 错误(至少是文档错误)。
你应该在 Python bug tracker... 中打开一个问题
问题与 lambda
无关,看起来像是在提供 locals
字典时由 exec 创建的闭包没有正确的范围解析。
奇怪的是 PyPy 有相同的行为,所以可能这确实是预期的结果(但是我不明白它在哪里记录)。
编辑
这可能看起来很奇怪,但这是预期的行为。
原因是当 exec
同时提供了 global
和 local
字典时,代码的执行就像它在 类定义的主体。
该上下文非常具体,在其中创建的闭包无法访问类范围内定义的名称(这就是为什么您需要在方法中使用 myclass.myattribute
来访问类属性 - 这是从全局开始的查找)。
这种奇怪的行为并不常见,因为通常在类定义范围内的代码只是进行简单的赋值(对于类级属性)和定义(对于方法),而不会 try catch 这些名称。
关于Python lambda+exec 范围错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31971588/