lambda:创建轻量匿名小函数,只能写单个表达式,不能写多行、不能写if语句块、for循环,表达式的结果自动作为返回值,不用写return。

基础语法

lambda 参数1,参数2 : 表达式

示例:

add = lambda a,b : a + b
print(add(2,3)) # 5

等价普通函数:

def add(a,b):
    return a + b

常用场景:配合sorted、map、filter

data = [("apple",3),("banana",1),("orange",2)]
# 按元组第二个元素排序
res = sorted(data, key=lambda x: x[1])
print(res)
nums = [1,2,3]
res = list(map(lambda x:x*2, nums))
print(res) # [2,4,6]

⚠️lambda经典大坑:延迟绑定(面试高频)

funcs = []
for i in range(3):
    funcs.append(lambda : print(i))

for f in funcs:
    f()
# 输出:
# 2
# 2
# 2

不是输出0,1,2;lambda捕获的是变量i本身,不是当时i的值;循环结束i=2,全部lambda执行的时候都拿最后i=2。

修复:给lambda增加默认参数,立刻捕获当时的值

funcs = []
for i in range(3):
    funcs.append(lambda val=i : print(val))

for f in funcs:
    f()
# 0 1 2

lambda 和闭包、刚才的UnboundLocalError关联

lambda内部赋值依然会触发局部变量规则,lambda里面不能做赋值语句,只能表达式。

# ❌ 错误,lambda内部不能写 cnt[0] +=1 这种赋值语句,这是语句不是表达式
bad = lambda : cnt[0] +=1

+=是赋值statement,lambda主体只能是expression,所以这种逻辑不能写lambda。

lambda 能不能用三元表达式(可以)

三元运算符是表达式,可以放lambda:

f = lambda x: x if x>0 else -x
print(f(-5)) #5

不推荐使用场景

  1. lambda逻辑复杂,三元套三元,可读性变差,直接换成def普通函数;
  2. 回调函数里面写很长的lambda,调试堆栈不好看;

速记

  1. lambda是匿名函数,只能单个表达式,隐式return,不能写多行代码块。
  2. 循环生成lambda要警惕延迟捕获变量,用默认参数val=i修复。
  3. 不能在lambda里面写赋值语句+=。
  4. 多用于sorted key、map、filter简短回调。

对比nonlocal / lambda小例子

def outer():
    cnt = [0]
    inc = lambda : (cnt.__setitem__(0, cnt[0]+1), cnt[0])[1]
    print(inc())
    print(inc())

outer()
# 输出1,2;只是演示,工程不要这么写,可读性极差,直接def函数。

工程实际:不要强行把多行逻辑塞进lambda,普通def优先。

更多推荐