众所周知,Python 支持多种编程范式:过程式(使用基础的语句)、面向对象编程和函数式编程。
Python 也提供了其他函数式编程语言的工具:
- 利用 map 在一个可迭代对象的各项上调用函数的工具
- 利用 filter 来过滤项
- 利用 reduce 把函数作用在成对的项上来运行结果的工具
一、map
在没有循环的情况下处理可迭代对象:map
有时我们需要对列表、集合、字典等可迭代序列做的一个操作就是:对其中每一个元素值进行某种操作,把其结果收集起来。
比如选出数据库中的某一列进行加减操作,或者针对某些特殊的值做平方的处理。
我们先来看一个例子:
1
2
3
4
5
6
7
8
9
|
>>> test = [ 1 , 2 , 3 , 4 , 5 , 6 ] >>> square = [] >>> for x in test: square.append(x * x) >>> square [ 1 , 4 , 9 , 16 , 25 , 36 ] >>> |
此时就可以利用 Python
的 map
,允许您在不使用循环的显式中处理和转换所有项目,该技术通常称为映射。当您需要将转换函数应用于可迭代并将其转换为新的迭代时,map 就能够有其用武之地。
1
2
3
4
5
6
7
8
|
>>> test = [ 1 , 2 , 3 , 4 , 5 , 6 ] >>> >>> def square(num): return num * num >>> list ( map (square, test)) [ 1 , 4 , 9 , 16 , 25 , 36 ] >>> |
如上,我们会传入一个自定义的函数 square()
来更加一般化地使用它,也就是对列表中的每一个元素都应用这个函数。
map 对列表中的每一个元素都调用了 square
函数,并将返回值收集到一个新的列表中。
正因为我们需要自定义一个 square 函数,结合上一篇文章 lambda
函数的简单介绍中。我们可以利用 lambda 直接生成这个匿名函数,也就是可以写出这样的代码实现相同的功能:
1
2
3
|
>>> list ( map (( lambda x: x * x), test)) [ 1 , 4 , 9 , 16 , 25 , 36 ] >>> |
map 传入内置 Python 函数
除了自定义函数,还可以 map 中传入内置的 Python 函数。例如,如果您有一个字符串列表,您可以轻松地创建一个计算该字符串列表长度的新列表:
1
2
3
4
|
>>> name = [ "Sam" , "Dwen" , "Kyrie" ] >>> list ( map ( len , name)) [ 3 , 4 , 5 ] >>> |
map 高级用法
map 不单能实现 for 循环能实现的同样的方式,还有性能优势。map 的高级用法比如:在一个可序列类型中,map 会按照顺序,并行地从各个序列中逐项取出一组又一组参数,然后传入函数中:
1
2
3
4
5
6
7
|
>>> pow ( 2 , 8 ) 256 >>> pow ( 3 , 8 ) 6561 >>> list ( map ( pow , [ 1 , 2 , 3 ], [ 8 , 8 , 8 ])) [ 1 , 256 , 6561 ] >>> |
能看到上述代码的结果,map 对传入的每个序列并行各自取一个值。
二、map 与列表推导式
map 调用其实与列表推导式相似。
1
2
3
4
5
|
>>> test = [ 1 , 2 , 3 , 4 , 5 , 6 ] >>> [x * x for x in test] [ 1 , 4 , 9 , 16 , 25 , 36 ] >>> list ( map (( lambda x: x * x), test)) [ 1 , 4 , 9 , 16 , 25 , 36 ] |
但是 map 在一般情况下会比列表推导式运行更快,而且编写的代码也会更少。而且有一点很重要:通过使用圆括号而不是方括号来包围一个推导,能创建一个按需产生值的对象,减少了内存又减少了程序的响应时间。
三、选择可迭代对象中的元素:filter
map 函数是将 Python 函数式编程工具集中一个主要也相对明确的代表。而 filter 和 reduce 分别实现了基于一个测试函数选择可迭代对象的元素,以及向”元素对“ 应用函数的功能。
下面来看一个调用 filter 挑出一个序列中大于零的元素:
1
2
3
4
|
>>> list ( range ( - 10 , 10 )) [ - 10 , - 9 , - 8 , - 7 , - 6 , - 5 , - 4 , - 3 , - 2 , - 1 , 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] >>> list ( filter (( lambda x : x > 0 ), range ( - 10 , 10 ))) [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] |
filter 对于序列或可迭代对象中的元素,如果函数对该元素返回了 True 值,这个元素就会被加入到结果列表中。
与 map 一样,filter 也能用一个 for 循环来等效,但是 filter 是内置的、简明的,通常也运行得更快:
1
2
3
4
5
6
7
8
|
>>> result = [] >>> for x in range ( - 10 , 10 ): if x > 0 : result.append(x) >>> resullt [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] |
同样的功能,我们也能用列表推导式来实现:
1
2
|
>>> [x for x in range ( - 10 , 10 ) if x > 0 ] [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] |
四、合并可迭代对象中的元素: reduce
Python的 reduce()
是一种函数,它在 Python 标准库中居住在一个名为 functools 的模块中:
1
|
from functools import reduce |
通过 reduce 来计算一个列表中所有元素加起来的和:
1
2
|
>>> reduce (( lambda x, y: x + y),[ 1 , 2 , 3 , 4 , 5 ]) 15 |
reduce
会将当前的和列表中的下一个元素传入列出的 lambda 函数,在默认条件下,序列中的第一个元素初始化了起始值。
使用 reduce 的这种用法也与如下使用 for 循环实现了同样的功能:
1
2
3
4
5
6
7
|
>>> test = [ 1 , 2 , 3 , 4 , 5 ] >>> result = test[ 0 ] >>> for x in test[ 1 :]: result = result + x >>> result 15 |
五、总结
- map 包括将转换函数应用于可迭代对象以生成新的可迭代对象。新迭代中的项是通过对原始迭代中的每个项调用转换函数来生成的。
- filter 包括将谓词或布尔值函数应用于迭代以生成新的可迭代。通过筛选原始可迭代中的任何项目,以使谓词函数返回 false 的任何项目生成的项目。
- reduce 包括将 reduce 函数应用于迭代以产生单个累积值。
到此这篇关于Python 函数式编程的三大法宝map+filter+reduce分享的文章就介绍到这了,更多相关Python 法宝map+filter+reduce内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://blog.51cto.com/yuzhou1su/5102651