将变量封装在闭包中以将其从函数签名中删除是一种常用于高效代码结构的技术。但是,在非嵌套 lambda 的情况下,闭包会保留变量的最终值,从而导致在尝试基于迭代变量访问特定值时出现问题。
请考虑提供的代码片段:
names = ['a', 'b', 'c'] def test_fun(name, x): print(name, x) def gen_clousure(name): return lambda x: test_fun(name, x) funcs1 = [gen_clousure(n) for n in names] funcs2 = [lambda x: test_fun(n, x) for n in names] # Expected output for funcs1 for f in funcs1: f(1) # Unexpected output for funcs2 (returns last element for all cases) for f in funcs2: f(1)
理解这种差异背后的原因对于有效利用闭包至关重要。
这种情况的基本概念是闭包中的变量作用域 。闭包本质上保存变量名称而不是它们的值。这意味着变量的求值发生在 lambda 执行启动时,而不是在 lambda 定义时。
对于 funcs2,当您执行 lambda x: test_fun(n, x) 时,变量 n在 lambda 定义期间不进行评估。相反,评估仅发生在 lambda 调用时。此时,n 保存循环中的最后一个值(在本例中为“c”)。因此,函数 f 始终使用“c”作为 n 的值,而不管输入 x。
要解决此问题并实现所需的功能,必须在 lambda 函数的作用域中捕获变量 n。这可以通过将变量作为参数传递给 lambda 来实现,如下所示:
funcs2 = [lambda x: test_fun(n, x) for n in names if 2 > 0]
通过包含这个始终成立的附加 if 语句,我们强制lambda 将 n 的值作为参数,确保在所有情况下都能实现预期的个性化行为。
或者,您可以将非嵌套 lambda 包装在嵌套中函数,有效防止访问作用域内未声明的变量。以下代码说明了这种方法:
def makeFunc(n): return lambda x: x+n stuff = [makeFunc(n) for n in [1, 2, 3]] for f in stuff: print(f(1))
这里,变量 n 在函数 makeFunc 中捕获,确保 lambda 内的范围正确。
理解和管理闭包中的变量作用域对于有效的代码设计和调试至关重要。关键要点是:
以上是如何处理非嵌套 Lambda 闭包中的变量作用域问题?的详细内容。更多信息请关注PHP中文网其他相关文章!