函数式编程之filter, map ,reduce和匿名函数lambda

一、函数式编程

函数式编程并非用函数编程这么简单,而是将计算机的运算视为数学意义上的运算,比起面向过程,函数式更加注重的是执行结果而非执行的过程,代表语言有:Haskell、Erlang。而python并不是一门函数式编程语言,但是仍为我们提供了很多函数式编程好的特性,如lambda,map,reduce,filter

二、 匿名函数与lambda

​ 对比使用def关键字创建的是有名字的函数,使用lambda关键字创建则是没有名字的函数,即匿名函数,语法如下
lambda 参数1,参数2,...: expression

举例

# 1、定义
lambda x,y,z:x+y+z

#等同于
def func(x,y,z):
    return x+y+z

# 2、调用
# 方式一:
res=(lambda x,y,z:x+y+z)(1,2,3)

# 方式二:
func=lambda x,y,z:x+y+z # “匿名”的本质就是要没有名字,所以此处为匿名函数指定名字是没有意义的
res=func(1,2,3)

匿名函数与有名函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,所以匿名函数用于临时使用一次的场景,匿名函数通常与其他函数配合使用,我们以下述字典为例来介绍它

salaries={
    'siry':3000,
    'tom':7000,
    'lili':10000,
    'jack':2000
}

要想取得薪水的最大值和最小值,我们可以使用内置函数max和min(为了方便开发,python解释器已经为我们定义好了一系列常用的功能,称之为内置的函数,我们只需要拿来使用即可)

>>> max(salaries)
'tom'
>>> min(salaries)
'jack'

内置max和min都支持迭代器协议,工作原理都是迭代字典,取得是字典的键,因而比较的是键的最大和最小值,而我们想要的是比较值的最大值与最小值,于是做出如下改动

# 函数max会迭代字典salaries,每取出一个“人名”就会当做参数传给指定的匿名函数key,
# 然后将匿名函数的返回值当做比较依据,最终返回薪资最高的那个人的名字
>>> max(salaries,key=lambda k:salaries[k]) 
'lili'
# 原理同上
>>> min(salaries,key=lambda k:salaries[k])
'jack'

sorted()方法 会产生新的内存地址(列表和字典都会) 而 .sort() 方法不会,,字典没有 .sort()方法
同理,我们直接对字典进行排序,默认也是按照字典的键去排序的

>>> sorted(salaries)
# ['jack', 'lili', 'siry', 'tom']
res=sorted(salaries,key=lambda k:salaries[k],reverse=True)
print(res) # ['lili', 'tom', 'siry', 'jack']

三、 map、reduce、filter

函数map、reduce、filter都支持迭代器协议,用来处理可迭代对象,我们以一个可迭代对象array为例来介绍它们三个的用法
array=[1,2,3,4,5]

要求一:对array的每个元素做平方处理,可以使用map函数
map函数可以接收两个参数,一个是函数,另外一个是可迭代对象,具体用法如下

>>> res=map(lambda x:x**2,array)
>>> res
<map object at 0x1033f45f8>
>>>

解析:map会依次迭代array,得到的值依次传给匿名函数(也可以是有名函数),而map函数得到的结果仍然是(map对象)迭代器。

>>> list(res) #使用list可以依次迭代res,取得的值作为列表元素
[1, 4, 9, 16, 25]

案例2, 要求列表的每一位末尾都加上_ds

l=['alex','lxx','wxx','yyy']
from collections.abc import Iterator,Iterable,Generator
res=map(lambda name:name+'_ds',l)
print(isinstance(res,Iterable)) # True
print(isinstance(res,Iterator)) # True
print(isinstance(res,Generator))# False
print(res) # <map object at 0x000001EA4B31B280>  如果是python2 将直接得到列表
print(list(res)) # ['alex_ds', 'lxx_ds', 'wxx_ds', 'yyy_ds']

结论: map对象是迭代器 有__iter__()__next__ ()方法。

要求二:对array进行合并操作,比如求和运算,这就用到了reduce函数
reduce函数可以接收三个参数,一个是函数,第二个是可迭代对象,第三个是初始值

# reduce在python2中是内置函数,在python3中则被集成到模块functools中,需要导入才能使用
>>> from functools import reduce 
>>> res=reduce(lambda x,y:x+y,array)
>>> res
15

解析:

  1. 没有指定初始值,reduce函数会先迭代一次array得到的值作为初始值,作为第一个值数传给x,然后继续迭代一次array得到的值作为第二个值传给y,运算的结果为3 (1+2)
  2. 将上一次reduce运算的结果3作为第一个值传给x,然后迭代一次array得到的结果3作为第二个值传给y,依次类推,直到迭代完array的所有元素,得到最终的结果15
    也可以为reduce指定初始值
>>> res=reduce(lambda x,y:x+y,array,100)
>>> res
115

要求三:对array进行过滤操作,这就用到了filter函数,比如过滤出大于3的元素fliter 函数接收两个参数 第一个参数可以返回bool值的过滤条件(True or False) 第二个是可迭代对象 ,得到的结果类似map ,仍为迭代器

>>> res=filter(lambda x:x>3,array)

解析:filter函数会依次迭代array,得到的值依次传给匿名函数,如果匿名函数的返回值为真,则过滤出该元素,而filter函数得到的结果仍然是迭代器。

>>> list(res) 
[4, 5]

案例2

# 方式一
l=['alex_sb','lxx_sb','wxx','张良']
res=(name for name in l if name.endswith('sb'))
print(res) # <generator object <genexpr> at 0x00CFF8B0>

# 方式二
res=filter(lambda name:name.endswith('sb'),l)
print(res) # <filter object at 0x000002582FBEB100>
print(isinstance(res,Iterable)) # True
print(isinstance(res,Iterator)) # True
print(isinstance(res,Generator)) # False

提示:我们介绍map、filter、reduce只是为了带大家了解函数式编程的大致思想,在实际开发中,我们完全可以用列表生成式或者生成器表达式来实现三者的功能。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值