函数式编程如何识别闭包?今天番茄加速就来分析一下。
先从一种比较好理解的方式入手,我们不使用 lambda,那样貌似把闭包隐蔽的太厉害了,不容易辨识出是闭包。
不过,下面这种方式,还是比较容易就能看出来吧。
In [19]: def exfun():
…: funli = []
…: for i in range(3):
…: def intfun(x):
…: print( x*i)
…: funli.append(intfun)
…: return funli
…:
…:
就是生成了一个list,里面的3个元素,元素类型是intfun()函数,它是一个闭包,引用了外部变量i
下面,我们调用函数:
In [20]: funli = exfun()
In [21]: funli0
10
In [22]: funli1
10
In [23]: funli2
10
有些意外,返回的都是10,按照我们的期望应该是0,5,10
这是为什么?
原因: i 是闭包函数引用的外部作用域的变量, 只有在内部函数被调用的时候, 才会搜索变量i的值。
由于循环已结束, i指向最终值2, 所以各函数调用都得到了相同的结果。
如何解决这个问题? 我们可以在生成闭包函数的时候,立即绑定变量 i,如下:
In [32]: def exfun():
…: funli = []
…: for i in range(3):
…: def intfun(x,i=i):
…: print( x*i)
…: funli.append(intfun)
…: return funli
…:
再次调用:
In [34]: funli0
0
In [35]: funli1
5
OK
真正在面试中,这道题会使用 lambda 进一步隐蔽闭包,呵呵,这回你可以识别出来了。
这是带陷阱的版本
In [38]: def exfun():
…: return [lambda x: i*x for i in range(3)]
这是OK版本:
In [38]: def exfun():
…: return [lambda x,i=i: i*x for i in range(3)]