明天的文章萌发于一个 python 试题:
参考了网上的解说都不甚清晰,咱们明天用白话文来解释一波
list1 = [lambda x: x + i for i in range(10)]
for list2 in list1:
print(list2(5))
执行后果:14
14
14
14
14
14
14
14
14
14
并不是咱们预期的后果,那么这个时候我的头脑里就呈现了一个首歌:小朋友,你是否有很多问号?
依照咱们的揣测,不应该是 5,6,7,8,9,10,11,12,13,14 这样的答案吗?
那么这个题看似简略,其实外部由很多的代码构造组成。这个时候就须要咱们去拆分这个语句了。
咱们都晓得,lambda 函数能够写成:
def fun1(x):
return x + i
那么,咱们的列表推导式拆开来写是怎么做到的呢,其实也是定义一个函数来实现列表数据的增加。
lst = []
def fun():
for i in range(10):
lst.append(i)
return lst
那么这个残缺的语句改写是怎么写的呢?
lst = []
def fun():
for i in range(10):
def fun1(x):
return x + i
lst.append(fun1)
return lst
r = fun()
print(r)
执行后果:[<function fun.<locals>.fun1 at 0x0000014FA44BEF28>, <function fun.<locals>.fun1 at 0x0000014FA44C30D0>, <function fun.<locals>.fun1 at 0x0000014FA44C31E0>, <function fun.<locals>.fun1 at 0x0000014FA44C3268>, <function fun.<locals>.fun1 at 0x0000014FA44C32F0>, <function fun.<locals>.fun1 at 0x0000014FA44C3378>, <function fun.<locals>.fun1 at 0x0000014FA44C3400>, <function fun.<locals>.fun1 at 0x0000014FA44C3488>, <function fun.<locals>.fun1 at 0x0000014FA44C3510>, <function fun.<locals>.fun1 at 0x0000014FA44C3598>]
大家对于这个构造是不是有那么一丢丢的相熟呢?
没错,他就是一个闭包函数,返回进去的后果就是一个列表外面寄存的 fun1 的函数对象。那么问题来了,既然是一个函数对象,咱们调用函数再给它传递参数,不应该就是咱们的预期后果吗?为什么全部都是 14 的后果呢?
这里就波及到了 python 的闭包函数的个性了:外部函数不通过非凡的形式没有方法批改内部函数的变量。
咱们这里应用的是内部函数的变量 i,那么当咱们的 for 循环执行完十次的时候,咱们列表中生成的每一个函数对象都是应用了变量 i 的,而且都是指向的内部函数中变量 i 的内存地址,那么当最初一次循环执行结束的时候,咱们的 i 是不是变成了 9,所以,每一个函数对象中的变量 i 的值都变为了 9,至此,当咱们去做 for 循环遍历这个列表并传递 x = 5 的值时,就都变为了 5 +9=14 的后果。
其余的 lambda 函数联合列表推导式都是同样的逻辑,你学废了吗?