乐趣区

关于python:列表推导式与lambda函数结合使用原理

  明天的文章萌发于一个 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 函数联合列表推导式都是同样的逻辑,你学废了吗?

退出移动版