MST

星途 面试题库

面试题:Python中lambda表达式与闭包及作用域的综合问题

编写一段代码,定义一个函数outer,它返回一个由lambda表达式组成的列表。lambda表达式的功能是将传入的参数与outer函数内部的一个变量相乘。在定义outer函数时,该内部变量的值为10。在调用outer函数后,对返回列表中的每个lambda函数传入参数5,并打印出结果。然而,在实际执行时结果可能并非预期,请分析原因并给出正确的实现,同时详细解释lambda表达式与闭包、作用域之间的关系是如何影响这段代码的行为的。
32.6万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

错误代码及分析

def outer():
    result = []
    for i in range(3):
        result.append(lambda x: x * i)
    return result

funcs = outer()
for func in funcs:
    print(func(5))

这段代码中,outer函数返回一个由lambda表达式组成的列表。本意是让每个lambda表达式将传入参数xi相乘,i在循环过程中依次为0, 1, 2。但实际执行时,lambda表达式中的i在调用时才取值,此时循环已经结束,i的值为2。所以每个lambda表达式执行的结果都是5 * 2 = 10。这是因为lambda表达式形成了闭包,它延迟绑定变量,在调用时才去查找变量的值,而不是在定义时就确定值。

正确实现

def outer():
    result = []
    for i in range(3):
        result.append(lambda x, j = i: x * j)
    return result

funcs = outer()
for func in funcs:
    print(func(5))

在这个正确实现中,通过在lambda表达式的参数列表中使用默认参数j = i,使得lambda表达式在定义时就绑定了i的值,而不是在调用时才去查找i的值。这样每个lambda表达式分别绑定了i的不同值,即0, 1, 2,所以输出结果为0, 5, 10。

lambda表达式、闭包与作用域关系解释

  1. lambda表达式:是一种匿名函数,简洁地定义小型函数。在上述代码中,用于创建简单的乘法函数。
  2. 闭包:由函数和与其相关的引用环境组合而成的实体。lambda表达式形成了闭包,它可以访问其定义时所在的外部作用域的变量。在错误代码中,lambda表达式访问了outer函数中的i,但由于延迟绑定,导致结果不符合预期。
  3. 作用域:在Python中,变量的作用域决定了变量的可见性和生命周期。lambda表达式所在的作用域链包括其自身的局部作用域、outer函数的局部作用域等。当lambda表达式访问变量时,会沿着作用域链查找,在错误代码中,lambda表达式在调用时沿作用域链找到的i是循环结束后的最终值。而在正确实现中,通过默认参数的方式,在lambda表达式定义时就确定了变量的值,避免了因作用域查找规则导致的问题。