面试题
def multipliers():
return [lambda x:i*x for i in range(4)]
print([m(2) for m in multipliers()])
这个题让我涨知识了,分享出来给大家看看,大神跳过
如果只看题,答案能做出来吗?
如果运行后,结果出来了,能分析出原因吗?
我这脑子反应较慢,所以呢研究了一下
总共涉及到:
1、列表推导式
2、匿名函数
3、闭包函数
4、for循环对函数的迭代调用
5、闭包函数的调用
有点恐怖,简简单单的题这么多知识点
列表推导式 :[xfor x in range(10)]这就是个简单的列表推导式,可以复制运行一下,就懂了
匿名函数也知道,匿名函数的关键字为lambda,表现形式为:lambda 参数 : 返回值,lambda后面的参数就是函数的形参,冒号后面的表达式就是返回值。
闭包函数:当前函数引用到上一层函数的局部命名空间的变量时就会触发闭包规则。我们说触发了闭包的函数叫做闭包函数,但是要注意一点:只有当调用闭包函数的时候它才会去引用外层函数的变量,因为在调用闭包函数之前,闭包内部的命名空间还不存在。
#根据前面的叙述,我们可以把它改成容易理解的形式:
def multipliers():
squares = []
for i in range(4):
res = lambda x:i*x
squares.APPend(res)
return squares
print([m(2) for m in multipliers()])
匿名函数使用了外部的变量i,触发了闭包规则
然后函数multipliers()的返回值是一个列表,这个列表的元素为四个闭包函数名指向的内存地址,虽然for i in range(4)这段代码里面的i的值分别被赋予了 0 1 2 3这四个值,但是闭包函数res并没有引用这四个值,因为闭包函数此时此刻还没有被真正调用,列表推导式仅仅是把四个匿名函数指向的内存地址保存在了一个列表里,因为没有调用,所以匿名函数内部的代码并没有执行,也就不存在引用。
所以函数multipliers()的返回值就是这样的一个列表:截图不全
相信到这里大家都明白的差不多了:
我们来看最后一条语句print([m(2) for m in multipliers()])
for m in multipliers() 这条语句到底干了什么?其实它干的事情只有一个,那就是遍历了函数multipliers()返回的列表,在遍历列表的同时把每个匿名函数赋值给了m,把它拆分来看就是这样:
m = lambda x:i*x
m = lambda x:i*x
m = lambda x:i*x
m = lambda x:i*x
并且每次都执行了一次 m(2),也就是每次都调用了一下匿名函数,注意:此时此刻匿名函数才真正被调用了,然后它会引用外层命名空间的变量i,那么此时i的值是多少呢?
因为for i in range(4)这个for循环已经执行完毕,i的值等于3,所以每次当执行m(2)时,i的值都等于3
所以每次调用m(2)的结果都是6
最终输出结果为[6, 6, 6, 6]
将它完全拆开
def multipliers():
# 先执行for循环,j变量更新为4,这个列表只是做了一个调用的工作,所以结果为4个8
squares = []
def l(i):
print('l')
print(i,j)
return i * j
for j in range(5):
print('for')
squares.append(l)
return squares
print([m(2) for m in multipliers()])
这个就很清晰了
相关阅读
1.public、private、protected和friendly的区别 都是访问类型修饰符关键字,在于访问范围不一样。 访问范围如下: 本类
1预处理 问题1:什么是预编译?何时需要预编译?答:预编译又称预处理,是整个编译过程最先做的工作,即程序执行前的一些预处理工作。主要处
转自: https://blog.csdn.net/csuzhaoqinghui/article/details/52107478一、微软58题A.逻辑推理1、你让工人为你工作7天,给工
1 预处理问题1:什么是预编译?何时需要预编译?答:预编译又称预处理,是整个编译过程最先做的工作,即程序执行前的一些预处理工作。主要处
这几天在网上搜集各种java面试题:一是为了自己能复习方便,二是为了分享给大家~~题目都是来自网上大佬的分享,感谢大佬们的贡献~~(持续