两道题目
- 题目1
def multipiers1():
return [lambda x: i*x for i in range(4)]
- 题目2
def multipiers2():
return (lambda x: i*x for i in range(4))
输出
- 题目1
print([m(2) for m in multipiers1()])
# [6, 6, 6, 6]
- 题目2
print([m(2) for m in multipiers2()])
# [0, 2, 4, 6]
带你探究为什么?
问题1:题目1和题目2函数返回分别是什么?
print(multipiers1())
# 输出
[<function multipiers1.<locals>.<listcomp>.<lambda> at 0x111bac400>, <function multipiers1.<locals>.<listcomp>.<lambda> at 0x111bac598>, <function multipiers1.<locals>.<listcomp>.<lambda> at 0x111bac488>, <function multipiers1.<locals>.<listcomp>.<lambda> at 0x111bac510>]
print(multipiers2())
# 输出
<generator object multipiers2.<locals>.<genexpr> at 0x1119926d0>
由上面可以看出,函数1返回的是四个函数的列表,函数2返回的是一个生成器。
其实懂点python基础的都知道,题目1返回的是列表生成式,当然列表生成式里面的元素就是lambda函数自身啦,题目2返回的生成器表达式,当然返回的就是生成器啦~
问题2:为什么题目1返回的是[6, 6, 6, 6]?
题目1产生的原因是:
Python 闭包的延迟绑定:这意味着内部函数被调用时,参数的值在闭包内
进行查找。因此,当任何由multipliers()返回的函数被调用时,i 的值将在附近的范围进行查找。那时,不管返回的函数是否被调用,for 循环已经完成,i 被赋予了最终的值3。
我的理解:
题目1返回的是函数,
- 相当于返回的是[lambda(2,i), lambda(2,i), lambda(2,i), lambda(2,i)],
- 但是函数是在运行的时候才需要使用到i的
- 然而i是个可变变量,在运行时后,i已经经历完for循环了
- 此时的i的值是3
(如果有不对的地方,欢迎提出~)
问题3:那题目2为啥返回[0,2,4,6]?
搞懂这个问题之前,我们先要记住问题1的答案,题目2返回的是什么?是函数吗?不是,是生成器!啥是生成器?emmm,好像懂但是又好像不懂?没关系,下面来搞明白一下下。
啥是生成器:
- 返回yield输出的函数
- (列表表达式)
生成器最重要的特点
当然仅仅知道啥是生成器还是不够的,还应该知道生成器的特点,生成器最大的特点就是惰性计算,即一次只计算出一个值。
那么第二题可以理解为,函数返回的是生成器,而且生成器里面的i值在for循环赋值的时候就已经被确定了。相当于返回的是lambda(0,x), lambda(1,x),lambda(2,x), lambda(3,x),通过next取值,然后进行计算。
网友评论