python中的函数式编程——apply, filter, map, reduce

时间:2021-08-14 19:23:07

什么是函数式编程?没有深入了解过,Scala就是函数式编程的语言,暂时可以把lambda当做是函数式编程

python有几个内建函数——apply, filter, map, reduce,这些函数的输入参数通常会有一个函数或者lambda表达式,类似于C++的函数指针。

apply已经废弃了,所以就不再研究了。

1、filter(bool_func, seq)

filter是过滤的意思,对于过滤来讲,如果满足条件就通过,否则就被过滤掉,所以说filter的第一个参数是一个返回值为bool的函数或者lambda表达式。

那么filter的作用是什么呢?内建函数filter的作用就是筛选出输入的seq列表中满足bool_func返回为True的元素,说起来费劲,还是直接看代码吧。

import random

def odd(n):
return n % 2

arr = []
for i in range(10):
arr.append(random.randint(0, 20))

print(arr)
print(filter(odd, arr))
最后的输出是:

[5, 10, 16, 17, 14, 4, 0, 7, 6, 12]
[5, 17, 7]
我们定义了odd函数,如果输入是奇数,返回True,否则返回False,那么调用filter之后,相当于是讲偶数过滤掉了,只留下奇数

在上面的程序中看到,我们专门定义了判断是否为奇数的函数,而在filter中传入了这个函数,这是不是很像C++中的函数指针?再想想,这儿完全可以用lambda表达式来代替啊。在最后一行加上

print(filter(lambda x : x % 2, arr))
结果输出:

[9, 0, 9, 4, 18, 7, 18, 10, 8, 19]
[9, 9, 7, 19]
[9, 9, 7, 19]
用定义函数和lambda的效果是完全一样的。这就是函数式编程!

2、map(func, seq)

这里的map和其他语言中的map不太一样,这里map的作用是将函数调用作用到输入seq的每个元素上,输入seq的个数和定义的函数的输入参数个数有关,先看下面代码:

a = [1, 2, 3, 5]
print(map(lambda x : x + x, a))
注意,这里我直接用lambda表达式了,完全可以用函数代替的,这个lambda表达式的作用是把将输入的数乘以2,最后结果如下:

[2, 4, 6, 10]
最后的结果是将列表中的全部元素扩大了2倍

需要注意的是可以输入多个列表,此时map会按顺序将每个列表的元素分别取出,依次执行func。

a = [1, 2, 3, 5]
b = [6, 7, 8, 9]
print(map(lambda x, y : x + y, a, b))
这里lambda表达式的作用是返回两个输入参数的和,最后得到

[7, 9, 11, 14]
由此可见,map的作用是c1 = a1 + b1, c2 = a2 + b2。。。在这里需要注意的是输入两个列表的最好等长,也不是说必须等长,这也要看lambda的作用,比如说是加减乘除,那必须相等,因为访问列表返回的None不能参与四则运算。

考虑一种特殊情况,如果指定的lambda为空,结果会怎样?

a = [1, 2, 3, 5]
b = [6, 7, 8, 9]
print(map(None, a, b))
最后的结果是:

[(1, 6), (2, 7), (3, 8), (5, 9)]
由此可见,是把连个列表归并成一个列表了。在python中有专门的归并函数zip,上面代码等价于zip(a, b)。

3、reduce(func, seq)

reduce的输入函数是一个二元函数,也就是是说两个参数的函数,而reduce(fun, [1, 2, 3])  => fun(fun(1, 2), 3)。基本上是一个迭代,reduce最后的输出只是一个数。

arr = range(10)
print(reduce(lambda x, y : x + y, arr))
最后的输出是:45

也就是说这段代码的作用是求0 + 1 + 2 + ... + 9的和。