python-匿名函数与函数式编程

匿名函数

匿名函数的关键字是 lambda,之后是一系列的参数,然后用冒号隔开,最后则是由这些参数组成的表达式。比如:

1
2
3
4
5
6
7
8
9
10
square = lambda x: x**2
square(3) # 9

========================
等价于
========================

def square(x):
return x**2
square(3) # 9

注意一:lambda 是一个表达式(expression),并不是一个语句(statement)

  • 所谓的表达式,就是用一系列“公式”去表达一个东西,比如x + 2、 x**2等等;

  • 而所谓的语句,则一定是完成了某些功能,比如赋值语句x = 1完成了赋值,print 语句print(x)完成了打印,条件语句 if x < 0:完成了选择功能等等。

因此,lambda 可以用在一些常规函数 def 不能用的地方,比如,lambda 可以用在列表内部,而常规函数却不能:

1
2
3
4
[(lambda x: x*x)(x) for x in range(10)]

# 输出
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

再比如,lambda 可以被用作某些函数的参数,而常规函数def 则不能:

1
2
3
4
5
6
l = [(1, 20), (3, 0), (9, 10), (2, -1)]
l.sort(key=lambda x: x[1]) # 按列表中元祖的第二个元素排序
print(l)

# 输出
[(2, -1), (3, 0), (9, 10), (1, 20)]

注意二,lambda 的主体是只有一行的简单表达式,并不能扩展成一个多行的代码块

什么时候使用匿名函数?

当我们需要一个函数,但它非常简短,只需要一行就能完成;同时它在程序中只被调用一次。

python 函数式编程

Python 主要提供了这么几个函数:map()、filter()、reduce(),通常结合匿名函数lambda一起使用。

map(function,iterable)

表示,对 iterable 中的每个元素,都运用 function这个函数,最后返回一个新的可遍历的集合。

1
2
l = [1, 2, 3, 4, 5]
new_list = map(lambda x: x * 2, l) # [2, 4, 6, 8, 10]

map()函数直接由C语言写的,运行时不需要通过python解释器间接调用,并且内部做了诸多优化,所以运行速度很快。

filter(function,iterable)

filter() 函数表示对 iterable 中的每个元素,都使用 function 判断,并返回 True 或者 False,最后将返回 True 的元素组成一个新的可遍历集合。

举个例子,比如要返回一个列表中的所有偶数,可以写成下面这样:

1
2
l = [1, 2, 3, 4, 5]
new_list = filter(lambda x: x % 2 == 0, l) # [2, 4]

reduce(function,iterable)

function 同样是一个函数对象,规定它有两个参数,表示对 iterable 中的每个元素以及上一次调用后的结果,运用 function 进行计算,所以最后返回的是一个单独的数。

举个例子,想要计算某个列表元素的乘积,就可以用 reduce()函数来表示:

1
2
l = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, l) # 1*2*3*4*5 = 120

总结

通常来说,在我们想对集合中的元素进行一些操作时,如果操作非常简单,比如相加、累积这种,那么我们优先考虑 map()、filter()、reduce() 这类或者 list comprehension 的形式。至于这两种方式的选择:

  • 在数据量非常多的情况下,比如机器学习的应用,那我们一般更倾向于函数式编程的表示,因为效率更高;

  • 在数据量不多的情况下,并且你想要程序更加 Pythonic 的话,那么 list comprehension 也不失为一个好选择。

不过,如果你要对集合中的元素,做一些比较复杂的操作,那么,考虑到代码的可读性,我们通常会使用 for 循环,这样更加清晰明了。