定义
在Python中,除了使用def关键字声明普通函数外,还提供了一种使用表达式生成函数对象的形式。由于它与LISP语言中的一个工具很相似,所以称为lambda。
lambda函数也叫匿名函数,即没有具体名称的函数,它允许快速定义单行函数,可以用在任何需要函数的地方。
lambda的语法形式如下:
lambda arg1, arg2, …, argN : expression
首先是关键字lambda;随后是一个或多个参数,其形式与用def定义函数的参数形式类似;紧跟的是一个冒号;最后是一个表达式,表达式使用的参数需要在冒号左边进行定义,表达式的结果即是该匿名函数的结果。
lambda语句构建的其实是一个函数对象,其示例如下所示:
>>> g = lambda x: x**2
>>> g
<function <lambda> at 0x7f36cba80c08>
与def的联系和区别
联系
由lambda表达式所返回的函数对象与由def创建并复制后的函数对象工作起来是完全一样的。
用def定义的求某个数的平方的函数f的代码如下:
>>> def f(x):
... return x**2
...
>>> f(4)
16
可使用lambda实现上述函数的功能
>>> g = lambda x: x**2
>>> g(4)
16
默认参数也能够在lambda参数中使用,就像在def中使用一样。
>>> x = (lambda a="hello", b=",", c="world": a + b + c)
>>> x()
'hello,world'
>>> x("hi")
'hi,world'
在lambda主体中的代码与在def内的代码一样,都遵循相同的作用域查找法则。lambda表达式引入的一个本地作用域更像一个嵌套的def语句,将会自动从上层函数中、模块中以及内置作用域中(通过LEGB法则)查找变量名。
>>> def test(title="Sir"):
... action = (lambda x: title + ' ' + x)
... return action
...
>>> act = test()
>>> act('robin')
'Sir robin'
区别
lambda和def具有如下区别:
- def定义的普通函数是有函数名称的,而lambda定义的函数并没有函数名称,因此也被称为匿名函数。
- lambda会返回一个函数对象,但不会为这个对象赋予一个标识符,而def则会把函数对象赋值给一个变量即函数名。
- lambda只是一个表达式,而def则是一个语句。 因为这一点,lambda能够出现在Python语法不允许def出现的地方,例如,在一个列表常量中或者函数调用的参数中。此外,作为一个表达式,lambda返回了一个值(一个新的函数),可以选择性的赋值给一个变量名。相反,def语句总是得在头部将一个新的函数赋值给一个变量名,而不是将这个函数作为结果返回。
- lambda是一个为编写简单的函数而设计的,而def用来处理更大的任务。lambda的主体是一个单个的表达式即冒号“:”后面只能有一个表达式,而def可以有多个即构成一个代码块。lambda仅限于表达式,使得其功能通常要比def少得多:只能够在lambda主体中将有限的逻辑封装进去,像if或for或print等语句都不能在lambda中使用,但是可以在def中使用。
- lambda函数不能共享给别的程序调用,def可以。
lambda与def定义的普通函数相比,只是省去了函数名称而已,而且这样的匿名函数又不能在别的地方调用。但是lambda还是具有如下优点:
- 使用Python写一些执行脚本时,使用lambda可以省去定义函数的过程,让代码更加精简。
- 对于一些抽象的,不会别的地方再复用的函数,有时候给函数起个名字也是个难题,使用lambda不需要考虑命名的问题。
- 使用lambda在某些时候让代码更容易理解。
与map/filter/reduce的联合使用
使用lambda定义的匿名函数可与Python提供的map、filter、reduce等全局函数结合使用,其示例如下所示:
>>> list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> map(lambda x: x * 2, list)
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
>>> filter(lambda x: x % 3 == 0, list)
[3, 6, 9]
>>> reduce(lambda x, y: x + y, list)
55
使用场景
替换形式
虽然可以在Python程序中使用lambda以达到一定的简洁程度,但是却并不一定非要使用lambda。
在对象遍历处理方面,Python语言提供的for..in..if语法非常强大,并且在易读性上胜过了lambda,比如在上面的map例子可以修改为如下:
>>> [x * 2 for x in list]
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
上面的filter例子可以修改为如下:
>>> [x for x in list if x % 3 == 0]
[3, 6, 9]
所以,什么时候使用lambda,什么时候不用,需要具体情况具体分析,只要表达的意图清晰就好。一般情况下,如果for..in..if能做的,尽量不要使用lambda。
常见问题
参数问题
如果想创建一个函数数组fs=[f_0, …, f_n],其中f_i(n)=i+n。于是定义了这么一个lambda函数:
>>> fs = [(lambda n: i + n) for i in range(10)]
>>> fs[3](4)
13
>>> fs[4](4)
13
>>> fs[5](4)
13
显然,这样定义的lambda函数并不能正确实现预期的功能。问题其实出在变量i上,lambda中的i使用的是匿名函数外的全局变量,即使用到的i的值都为9。可将代码修改为如下:
>>> fs = [(lambda n, i=i : i + n) for i in range(10)]
>>> fs[3](4)
7
>>> fs[4](4)
8
lambda的例子
lambda的使用情况及不适用情况