函数式编程 高阶函数 map&reduce filter sorted
函数式编程
纯函数:没有变量的函数
对于纯函数而言:只要输入确定,那么输出就是确定的。纯函数是没有副作用的。
函数式编程:允许把函数本身作为参数传入另一个函数,还允许返回一个函数
高阶函数:一个函数的参数中包含了另一个函数
def add( x , y , f ): return f ( x ) + f ( y )
如果传入参数 -5 , -6 , abs
则该函数就等价于:
abs( -5 ) + abs ( -6 )
map
说明
将函数作用到Iterable中的每个元素上,返回作用后的元素构成的Iterator。如果要得到List,可以用list()进行强制转化
用法
map( func , iterable )
map函数接收两个参数——第一个是一个函数,第二个是Iterable
例子
求一个序列的平方
from collections.abc import Iterator def f(x): return x*x L=range(1,11) L2=map(f , L) isinstance(L2,Iterator) print(list(L2)) #输出 True [ 1, 4, 9, ……, 81, 100 ]
map函数返回一个Iterator,需要时应转化为需要的类型(本例中用强制类型转换为了List类型)。
批量处理集合元素
结合以前的知识,要相对一个集合元素进行批量统一的处理,暂时有两种好的方法:
- 列表生成式
- map
举个例子,将一个List中的元素全部转化为字符串str
#列表生成式 [str( x ) for x in range(1,11)] ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] #map list( map( str , range(1,11) ) ) ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
reduce
参数方面和map一样,接收两个参数——函数,集合序列
这里的函数传入参数必须为两个(与map不同点之①)
作用:从第一个元素开始,和第二个元素作为参数,进行函数计算,结果和第三个元素作为参数,进行函数计算……
简而言之,第一个元素和第二个元素,函数运算,结果和第三个元素,函数运算,……,结果和最后一个元素,函数运算
用伪代码可以简述为:
reduce( f, [x1,x2,x3] ) #等价于 f ( f ( x1 , x2 ) , x3 )
返回一个值而非Iterator(不同点之②)
需要注意的是,使用reduce时需要手动从functools库中导入,而map不需要(不同点之③)
from functools import reduce
举例
由序列 [ 1, 3, 5 ,7 ]转化得到数字1357
def f(x,y): return 10*x+y print(reduce(f,range(1,10,2)))
map&reduce综合
例1
不用强制类型转换int(),将一个字符串转化为整数(假设这个字符串就是类似'123456'这种类型)
from functools import reduce A=[str(x) for x in range(0,10)] B=range(0,10) D=dict(zip(A,B)) #构造整数字符与整数对应的Dict对象 def char2num(x): #返回某字符对应的整数 return D[x] def sum2(x,y): #用于reduce,从前往后得到的单个整数每多一位就乘10 return 10*x+y; def str2int(s): return reduce(sum2,list(map(char2num,s))) #3步 #1、map(char2num,s) 把S中的字符全部转化为对应的整数 #2、list() map结果化为List #3、reduce 不断 高位乘10+低位 print(str2int('123456')) 123456
例2
将一个字符串小数转化为浮点数('123.456')
from functools import reduce A=[str(x) for x in range(0,10)] B=range(0,10) D=dict(zip(A,B)) S='123.456' tag=S.find('.') len1=tag len2=len(S)-tag-1 #下标 0到tag-1为整数部分 #下标 tag+1到len-1为小数部分 def char2num(ch): return D[ch] def add1(x,y): return x*10+y def str2flo(S): N1=reduce(add1,list(map(char2num,S[:tag]))) N2=reduce(add1,list(map(char2num,S[tag+1:]))) return N1+N2/pow(10,len2) print(str2flo('123.456'))
filter
参数:同map
filter( func , iterable )
说明
过滤/筛选序列——将函数作用于序列中的每个元素,根据返回值是True还是False决定保留还是丢弃该元素(True——保留,False——丢弃)
实际使用时:筛选函数的参数不一定是作用的序列元素,作用方式最终取决于筛选函数的return中的变量(见例三)
返回值
返回一个Iterator,要求返回list时要用强制类型转换list( )
例子
1、删去一个list中的所有偶数
def f(x): return x%2 list(filter(f,range(1,11))) [1, 3, 5, 7, 9]
2、删去一个字符串中的空字符串(包含空字符串和全空格字符串)
def f2(s): return s and s.strip() list(filter(f2,['123',' A ','',' h',' '])) ['123', ' A ', ' h']
3、用filter求素数
#得到一个奇数数列,偶数人为排除 def odd_list(): n=1 while True: n=n+2 yield n #筛选函数,筛选的变量是x而非n def not_divisible(n): return lambda x: x%n def primes(): yield 2 it=odd_list() while True: n=next(it) yield n it=filter(not_divisible(n),it)#对序列中的每个数进行筛选
for n in primes(): if n<100: print(n) 2 3 5 …… 97
sorted
sorted( List, key ,reverse)
传入参数有三个:序列(必须是List类型)、函数、是否反向(后两个可以缺省)
第二个参数缺省时,排序方式为数学大小(字符串则为每个字母的ASCII码)
作用:先对序列中的每个元素进行函数处理,对处理后的序列进行排序(方式为数学大小),返回排序后的新序列(先函数,再排序,结果为排序结果),并不改变原序列(区别于list.sort)。
注意,
1、key=函数,函数后不加括号,即只是函数名,如key=abs
2、key函数,不是真正的排序函数,而是对序列元素进行处理的函数。处理完的排序方式仍为数学大小(例子见例五)
3、第二个参数 ' key=函数 ',是一个默认参数,这个key=不要忘记,这一点与之前的map,reduce,filter不同
4、sorted排序结果不作用于原List,请用一个新的变量去承接排序结果:
newL=sorted(oldL,key=func)
例一:
sorted( [1,9,5,-1,20,-10] ) [-10, -1, 1, 5, 9, 20] sorted(['alen','Jim','Aim','Zen','Qee']) ['Aim', 'Jim', 'Qee', 'Zen', 'alen']
例二:按绝对值大小排序
sorted([1,9,5,-1,20,-10],key=abs)
[1, -1, 5, 9, -10, 20]
例三:对字符串,不分大小写,按字母顺序排序
sorted(['alen','Jim','Aim','Zen','Qee'],key=str.lower) ['Aim', 'alen', 'Jim', 'Qee', 'Zen']
例四:对例三的结果反向排序
#补上反向排序参数reverse=True sorted(['alen','Jim','Aim','Zen','Qee'],key=str.lower,reverse=True) ['Zen', 'Qee', 'Jim', 'alen', 'Aim']
例五:对一组Tuple排序
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
按名字进行排序
sorted( L, key=lambda x:x[0] )
[('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]
总结:
1、map(f , I) : 将f作用于Iterable的每个元素上,返回一个Iterable,需要用强制类型转换list()将Iterable转化为list对象。
2、reduce(f , I):f必须有两个参数,返回一个值。对I的前两个元素进行f,结果和第三个元素进行f,结果和第四个元素进行f……结果和最后一个元素进行f。
3、filter(f , l):将f作用于Iterable的每个元素上,根据作用结果是True还是Fasle选择保留或放弃这个元素,返回筛选后的Iterable,需要用list将Iterable转化为list对象。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性