Python Tip 3: Python lambda表达式

Python中的Lambda表达式很可能让人迷惑,我们还是从一段官方解释文字开始:

Small anonymous functions can be created with the lambda keyword. This function returns the sum of its two arguments: lambda a, b: a+b. Lambda functions can be used wherever function objects are required. They are syntactically restricted to a single expression. Semantically, they are just syntactic sugar for a normal function definition.

理解lambda表达式的本质需要回答两个问题:为什么需要lambda?lambda的好处在哪里?

首先为什么需要lambda? 让我们看几个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
>>> add_one = lambda x: x + 1
>>> add_one(1)
2
>>> add_one(2)
3
>>> add_one(100)
101
>>> def add_one_fun(x):
...     return x + 1
... 
>>> add_one_fun(1)
2
>>> add_one_fun(100)
101
>>> x_sum_y = lambda x, y: x + y
>>> x_sum_y(1, 1)
2
>>> x_sum_y(1, 10)
11
>>> def sum_fun(x, y):
...     return x + y
... 
>>> sum_fun(1, 1)
2
>>> sum_fun(1, 2)
3
>>> sum_fun(1, 10)
11

很遗憾,lambda并非必须,每个lambda都可以用函数替代。那么我们为什么需要lambda表达式?或者lambda表达式有什么优点?其实,官方文档里已经说得很明确了:首先,它是一个小的匿名函数,可以用在任何需要函数对象的地方,它的语法被严格限制在一行表达式(并且不应该太复杂);从语义上来讲,它们只是正常的函数定义的语法糖。

Python不是一个纯函数式编程语言,但是引入了sorted, map, reduce, filter等函数式编程的一些特性, 可以将函数作为参数传给这些函数,这里,lambda表达式就派上用场了。我们熟悉的大概是sorted函数了:

1
2
3
4
5
>>> test_list = [('two', 2), ('three', 3), ('one', 1), ('five', 5), ('four', 4)]
>>> sorted(test_list, key=lambda x: x[1])
[('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]
>>> sorted(test_list, key=lambda x: x[0])
[('five', 5), ('four', 4), ('one', 1), ('three', 3), ('two', 2)]

map() 接收一个 function 和一个 iterable 作为参数,该函数会返回一个迭代器,该迭代器将 function 应用于 iterable 的所有元素,并产生结果。下述示例,对列表中所有元素求平方和立方:

1
2
3
4
5
6
7
>>> test_list = [2, 3, 5, 7, 11, 13, 19, 17]
>>> map_list = list(map(lambda x: x ** 2, test_list))
>>> map_list
[4, 9, 25, 49, 121, 169, 361, 289]
>>> map_list = list(map(lambda x: x ** 3, test_list))
>>> map_list
[8, 27, 125, 343, 1331, 2197, 6859, 4913]

reduce() 函数会对参数序列中元素进行累积。函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。注意在python3中reduce已经从全局函数中移除,需要从functools中import,我们来看一个1到100整数求和的例子:

1
2
3
4
5
6
>>> test_list = list(range(1, 101))
>>> test_list
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
>>> from functools import reduce
>>> reduce(lambda x, y: x + y, test_list)
5050

filter() 提供了一种优雅的方法来过滤 iterable(可迭代对象,例如:列表)中的所有元素,过滤条件是 function 返回 True:

1
2
3
4
5
6
7
>>> test_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
>>> filter_list = list(filter(lambda x: x % 3 == 0, test_list))
>>> filter_list
[3, 6, 9, 12, 15]
>>> filter_list = list(filter(lambda x: x % 5 == 0, test_list))
>>> filter_list
[5, 10, 15]

注:原创文章,转载请注明出处及保留链接“Python时代”:http://www.pythonage.com/

本文链接地址:Python Tip 3: Python lambda表达式 http://www.pythonage.com/?p=47