匿名函数lambda
Python使用lambda关键字创造匿名函数。所谓匿名,意即不再使用def语句这样标准的形式定义一个函数。这种语句的目的是由于性能的原因,在调用时绕过函数的栈分配。其语法是:
lambda [arg1[, arg2, ... argN]]: expression
其中,参数是可选的,如果使用参数的话,参数通常也会在表达式之中出现。
无参数
# 使用def定义函数的方法 def true(): return True #等价的lambda表达式 >>> lambda :True <function <lambda> at 0x0000000001E42518> # 保留lambda对象到变量中,以便随时调用 >>> true = lambda :True >>> true() True
一个参数
# 使用def定义的函数 def add( x, y ): return x + y # 使用lambda的表达式 lambda x, y: x + y # lambda也允许有默认值和使用变长参数 lambda x, y = 2: x + y lambda *z: z # 调用lambda函数 >>> a = lambda x, y: x + y >>> a( 1, 3 ) 4 >>> b = lambda x, y = 2: x + y >>> b( 1 ) 3 >>> b( 1, 3 ) 4 >>> c = lambda *z: z >>> c( 10, 'test') (10, 'test')
lambda是单个的表达式,不是一个代码块 lambda的设计是为了满足简单函数的场景,仅能封装有限的逻辑,有复杂逻辑的情况有def来处理,所以lambda的功能要比def小的多
lambda表达式是可以嵌套的(闭包)
>>> action = (lambda x : (lambda y : x + y)) >>> a = action(10) >>> a(5) 15
匿名函数的使用
匿名函数通常被用作高阶函数(higher-order function,参数为函数的函数)的参数。比如,几个内置函数:filter(),map(),reduce()。下面我们分别看看这几个函数的用法及达到相同效果的python另一种特征的用法
filter函数
>>> list = [1, 2, 3] >>> result = filter(lambda x: x%2==0, list) >>> result [2] >>> result = [x for x in list if x%2==0] >>> result [2]
map函数
>>> result = map(lambda x: x*2, list) >>> result [2, 4, 6] >>> result = [x*2 for x in list] >>> result [2, 4, 6]
reduce函数
>>> result = reduce(lambda x, y: x+y,list) >>> result 6 >>> result = sum(list) >>> result 6
跳转表(jump table)
lambda的另一种用法是用来编写跳转表,也就是行为列表或字典,能按需执行特定的动作。
>>> key = "get" >>> {"abc":(lambda : 2 + 2),"bcd" : (lambda : 3 + 3), "get" : (lambda : 4 + 4)}
[key]() 8
注意问题:
x = 10 a = lambda y: y + x x = 20 b = lambda y: y + x #猜想一下:a(10) 和 b(10)返回的结果是什么?如果你认为结果是20 和 30,那么就错了 print(a(10)) ##输出:30 print(b(10)) ##输出:30
lambda
表达式中的x是一个自由变量, 是在运行时绑定值,而不是定义时就绑定,即lambda表达式中的x是执行时的值,这与函数的默认值参数定义是不同的。例如:
x = 15 print(a(10)) ##输出:25 x = 3 print(a(10)) ##输出:13
如果想让匿名函数,在定义时就捕获到参数值,可以将那个参数值定义成默认参数即可,例如:
m = 4 c = lambda n, m = m: m + n print(c(10)) ##输出:14 m = 2 print(c(10)) ##输出:14
有时候,可能会不恰当的使用lambda
表达式。 比如,通过在一个循环或列表推导中创建一个lambda
表达式列表,并期望函数能在定义时就记住每次的迭代值。例如:
funcs = [lambda x: x+n for n in range(3)] for f in funcs: print(f(0)) # 2 # 2 # 2
但是实际效果是,n的值为迭代的最后一个值。将参数值设置为默认参数,才能得到想要的效果,修改代码如下:
funcs = [lambda x, n = n: x+n for n in range(3)] for f in funcs: print(f(0)) # 0 # 1 # 2