对lambda 函数的粗浅理解


关于 lambda 函数的理解,当我在A Byte of Python 中第一次看到它的时候,彻底被搞糊涂了。但是凭着我对一行式程序的爱好,我接着看了Dive into Python, Python Tutorial 和Python Quick Reference 终于可以说稍微理解了一下这种Functional Programming 手法的大致概念了。

为了不至于很快忘记,我最好还是把现在脑中的思路写下来,顺便也能整理一下,看看自己的理解有没有问题。

首先,lambda 函数的格式是这样的:

lambda parameters: expression

parameters是填写函数参数的地方,而expression是填写函数表达式的部分。
并且因为parameters是复数,所以函数的参数就可以是多个,并且支持默认参数。
而expression部分则规定了只能写一行的表达式。
至于函数的返回值,那自然就是表达式的运算结果了。

简而言之,lambda 函数就是一个没有函数名称,且只支持一行表达式的简易函数。
没错,lambda 函数就是一种语法糖,但是这种语法糖的存在让后面的几种例子的实现表现得不像以往那么累赘并且丑陋了。

我们再来回顾一下,既然lambda 函数谓之函数,那么就应该有函数所具有的特性。也就是说,它可以被赋值于一个变量,然后使用变量来调用函数并实现功能。
所以下面的例子在语法上完全没有问题。

>>> g = lambda x: x*2
>>> g(3)
6

当然也可以不通过变量来调用lambda 函数

>>> (lambda x: x*x)(3)
9

通过以上的例子,我们可以使用lambda 函数来动态配置函数中常量。类似:

>>> def make_incrementor(n):
...     return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43

这个例子里首先定义了make_incrementor 函数,它接受参数n 并赋予内部的lambda 函数。
最后make_incrementor 函数返回内部被定制的lambda 函数。
在例子中变量f 被定义成定制了数字42的lambda 函数。
而调用f 指向的函数,并赋予参数时,就执行定制好了的lambda 函数内部的x + 42的表达式。

通过把lambda 函数赋值给变量的操作,不光可以实现定制函数,还能根据某个布尔型变量动态选择想要执行的函数,就好似一个十分简单的状态机。

>>> Condition = True
>>> ObjectString = "my_email_address gmail.com"
>>> processFunc = Condition and (lambda s: "@".join(s.split())) or (lambda s: s)
>>> processFunc(ObjectString)
'my_email_address@gmail.com'

布尔类型变量Condition 的值直接影响到processFunc 指向的函数。
要注意,一旦决定了processFunc 的指向,在这之后即使改变Condition 的值而不再对processFunc 进行重新指向的话,processFunc 的指向时不会发生变化的。

在接近终点之前,让我们结合Functional Programming 的另一代表filter 来看看lambda 函数在其中扮演的角色吧。

>>> aList = range(1, 10)
>>> aList
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> low = 3
>>> high = 7
>>> filter((lambda x, l=low, h=high: h > x > l), aList)
[4, 5, 6]

通过filter 对aList的遍历,把从aList中取出的每一个值赋予x并参与到指定lambda 函数的运算中,得到新的list。

以上的例子其实可以用List Comprehensions 更简单的实现:

>>> [d for d in aList if 7 > d > 3]
[4, 5, 6]

类似的替代还有很多,正如许多文章中说的,lambda 函数确实是一种语法糖。
但是通过这种语法糖,有时候可以把很多需要简单函数的地方简化,省却了建立函数的步骤,甚至不用费力去想函数的命名。
在另一方面, lambda 函数结合Functional Programming 的三大利器filter, map, reduce 对常量进行的操作确实可以实现一种新的思维方式。

以上的例子都直接取自或者修改于Dive into Python, Python Tutorial 和Python Quick Reference。

Tagged on:

2 thoughts on “对lambda 函数的粗浅理解

  1. Mr.Bear

    @wayne: 嗯,确实如此。如果C也有lambda的话,那些靠switch…case实现的状态机就可以从此退休了。代码瞬间就干净很多。

发表评论

电子邮件地址不会被公开。