前言
最近做某公司的数据挖掘岗的笔试题,遇到一道python题,让我印象深刻。如下
def num():
return [lambda x:x*i for i in range(4)]
print([m(?) for m in num()])
如果打印的结果为[6,6,6,6]
,问❓处的数字应该为多少?
分析
首先,很显然的,num()
函数返回的是4个匿名函数组成的列表,那么遍历这4个函数并调用的结果就是我们的打印结果。如果不仔细想清楚,会很自然的认为答案就是[0*❓,1*❓,2*❓,3*❓]
。但是如果是这样,那么无论❓处输入什么数字,结果都不是[6,6,6,6]
。这也是我当时第一眼的想法。但是,如果我们我们再仔细想一想,就会发现num()
函数内部构成闭包,我们可以将其改写为如下更易懂的形式。
def num():
func_li=[]
for i in range(4):
def func(x):
return x*i
func_li.append(func)
return func_li
# 真正的执行
for func in num():
print(func(❓))
在我们调用num()
中的每个func()
时,func()
才开始去寻找需要的参数i,因为函数内部根本找不到i这个变量,但是这个时候,内部的for循环结束,此时存在变量i=3,因此对于调用每个func()
来说,返回的结果都是x*3。当明白这个点之后,这个问题也就迎刃而解了,❓处的数字自然就是2。
如果我们希望当❓处数字为2时,输出的结果是[0,2,4,6]
,那么可以将num()
修改为如下
def num():
return [lambda x,i=i:x*i for i in range(4)]
即让每个函数都存储当前for循环的i值。