面试题答案
一键面试Lambda函数闭包形成过程及作用域分析
- 函数定义与作用域:
- 首先定义了
outer
函数,在outer
函数内部定义了变量x
并赋值为10
,x
的作用域是outer
函数内部。 - 接着在
outer
函数内部定义了inner
函数,inner
函数形成了一个嵌套作用域。在Python中,嵌套函数可以访问外部函数的变量,这是闭包形成的基础。
- 首先定义了
nonlocal
关键字:inner
函数中使用了nonlocal x
,这表明x
不是inner
函数的局部变量,而是引用外部(但非全局)作用域中的x
变量。当执行x = 20
时,它修改的是outer
函数中的x
变量,而不是在inner
函数内部创建一个新的局部变量x
。
- Lambda函数与闭包:
inner
函数返回了一个Lambda函数lambda y: x + y
。这个Lambda函数捕获了inner
函数作用域中的x
变量,形成了闭包。闭包是一种函数对象,它记住了定义时的环境,即使在定义的环境已经不存在的情况下,仍然可以访问这些变量。- 当
outer
函数返回inner()
时,outer
函数的执行环境在正常情况下应该结束,但由于返回的Lambda函数形成了闭包,它保留了对outer
函数中x
变量的引用。
- 最终输出结果分析:
- 调用
f = outer()
,outer
函数执行,x
被赋值为20
,返回的Lambda函数被赋值给f
。 - 调用
f(5)
,此时Lambda函数执行,它将捕获的x
值(此时为20)与传入的参数y = 5
相加,所以结果为20 + 5 = 25
。
- 调用
注释掉nonlocal x
后的错误分析
- 错误类型:如果将
nonlocal x
这一行注释掉,代码会抛出UnboundLocalError
。 - 原因:当Python遇到
x = 20
语句时,它会默认x
是inner
函数的局部变量。但是在赋值语句之前,Lambda函数试图访问x
的值(x + y
),而此时x
作为局部变量还没有被赋值,所以会引发UnboundLocalError
。Python在处理变量时,会根据变量的使用情况来判断它的作用域类型,这里因为有x = 20
这样的赋值语句,所以Python将x
视为inner
函数的局部变量,而不是外部函数的变量,从而导致了错误。