我有以下资料:
x = [1,2,3,4,5]
def foo(lbd:str, value):
ret_val = eval(lbd, globals(), locals())
print(ret_val)
在此调用中使用“value”变量成功:
>>> foo("[i for i in value]",x)
[1, 2, 3, 4, 5]
但这一次失败了:
>>> foo(r"any([x in value for x in {'',0,None,'0'}])", x)
Traceback (most recent call last):
File "<pyshell#171>", line 1, in <module>
foo(r"any([x in value for x in {'',0,None,'0'}])", x)
File "<pyshell#165>", line 2, in foo
ret_val = eval(lbd, globals(), locals())
File "<string>", line 1, in <module>
File "<string>", line 1, in <listcomp>
NameError: name 'value' is not defined
我能够解决这个问题,但很想知道这里发生了什么
>>> foo(r"(lambda V=value: any([x in V for x in {'',0,None,'0'}]) )()", x)
False
这是一个非常微妙的观点。因此,如果您阅读documentation for ^{} ,它没有提到为全局变量和局部变量提供参数的情况,但我相当确定它的工作原理与for ^{} 相同:
在类定义中,函数无法访问其封闭范围。因此,这与错误完全相同:
因为列表理解是通过在引擎盖下创建函数对象来工作的。这也是为什么需要
self.some_method
来访问类中定义的其他方法的名称。有关上述内容的更多信息,请参见the excellent accepted answer here因此,这与:
但是,这很管用:
因为不涉及(非)封闭的功能范围
最后,以下原因起作用:
这是因为理解的最左边的for子句中的iterable不是在理解的函数范围内计算的,而是在理解发生的范围内计算的(它实际上是作为参数传递的)。您可以在列表的分解中看到这一点:
注意,
values
被计算,对其调用iter
,其结果被传递给函数:“函数”基本上只是一个带有append的循环,有关列表理解是如何工作的,请参见:
Disassembly of <code object <listcomp> at 0x7fe28baee3a0, file "<dis>", line 1>
除了@juanpa.arrivillaga的answer之外,在this bug report中还讨论了这种行为(它不是一个bug)
这里有一个快速解决您眼前问题的方法:
相关问题 更多 >
编程相关推荐