来说说lambda


看python cookbook时候被这个问题困扰然后就花了不少时间在这上面

首先了解lambda函数,又被称为匿名函数

  1. lamda (参数):返回值表达式
  2. 参数在传入时候也可以设置默认值
  3. 要注意的一点是,lambda函数的参数是在每次调用时候传入,并不是在定义lambda函数时就被传入
  4. 所有的函数都是如此,即在执行时候才会传入值,而不是定义时

先来看两个,我一直在想为什么第一个输出的全都是4

func = [lambda x: x + n for n in range(5)]
for f in func:
    print(f(0))

4
4
4
4
4
funcs = [lambda x, n=n: x + n for n in range(5)]
for f in funcs:
    print(f(0))

0
1
2
3
4

解答

由姚前 - vimiix大神提供的关于闭包概念的详解

闭包:闭包是由函数及其相关的引用环境组合而成的实体

结合例子来看,lambda x: x + nlambda x, n=n: x + n就是一个在for循环中的闭包函数,其执行过程类似以下代码:

def f1(x):
    flist = []
    for n in range(5):
        def add():
            return x + n
        flist.append(add)
    return flist

for f in f1(0):
    print(f())
def f2(x):
    flist = []
    for n in range(5):
        def add(n1=n):
            return x + n1
        flist.append(add)
    return flist

for f in f2(0):
    print(f())

小知识

这里我插入另一个小知识点,调用函数时候加不加括号的区别
知道的朋友就直接跳过啦

f = func
将func这一函数对象赋予f
f = func()
函数执行,将执行结果赋予f

比如上面的f1,我将其稍作修改,其结果会完全不同

def f1(x):
    flist = []
    for n in range(5):
        def add():
            return x + n
        flist.append(add())  # 将add()执行的结果返回,分别为0,1,2,3
    return flist

for f in f1(0):
    print(f)  # 这时候我们只能用f而不是f(),因为此时f不是函数对象了,而是一个值

回归正题

结合以下几个特性:

  1. python中循环的值在循环结束后不被销毁而是继续存在并且可以被调用
  2. 函数在执行时才传入参数
  3. 带括号的函数才是被执行的,不带括号则是引用该函数对象

对于func = [lambda x: x + n for n in range(5)],其执行过程见下图

来说说lambda_第1张图片
图像 1.png

而对于lambda x, n=n: x + n for n in range(5)
它的不同之处在于在其内部的n指向的是当前循环的n值
这样比较拗口,改写为lambda x, n1=n: x + n1 for n in range(5)这样就清晰得多了


结束

以上,有的时候思考一下编程中的这种小陷阱虽然挺容易让人崩溃的,但只要想通了其中的逻辑,就很明了了。

你可能感兴趣的:(来说说lambda)