前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >详解Python函数式编程之map、reduce、filter

详解Python函数式编程之map、reduce、filter

作者头像
Python小屋屋主
发布2018-04-16 15:24:06
1.2K0
发布2018-04-16 15:24:06
举报
文章被收录于专栏:Python小屋Python小屋

map()、reduce()、filter()是Python中很常用的几个函数,也是Python支持函数式编程的重要体现。不过,在Python 3.x中,reduce()不是内置函数,而是放到了标准库functools中,需要先导入再使用。

(1)map()。内置函数map()可以将一个函数依次映射到序列或迭代器对象的每个元素上,并返回一个可迭代的map对象作为结果,map对象中每个元素是原序列中元素经过该函数处理后的结果,该函数不对原序列或迭代器对象做任何修改。 >>> list(map(str, range(5))) #把列表中元素转换为字符串 ['0', '1', '2', '3', '4'] >>> def add5(v): #单参数函数 return v+5 >>> list(map(add5, range(10))) #把单参数函数映射到一个序列的所有元素 [5, 6, 7, 8, 9, 10, 11, 12, 13, 14] >>> def add(x, y): #可以接收2个参数的函数 return x+y >>> list(map(add, range(5), range(5,10))) #把双参数函数映射到两个序列上 [5, 7, 9, 11, 13] >>> list(map(lambda x, y: x+y, range(5), range(5,10))) [5, 7, 9, 11, 13] >>> def myMap(iterable, op, value): #自定义函数 if op not in '+-*/': #实现序列与数字的四则运算 return 'Error operator' func = lambda i:eval(repr(i)+op+repr(value)) return map(func, iterable) >>> list(myMap(range(5), '+', 5)) [5, 6, 7, 8, 9] >>> list(myMap(range(5), '-', 5)) [-5, -4, -3, -2, -1] >>> list(myMap(range(5), '*', 5)) [0, 5, 10, 15, 20] >>> import random >>> x = random.randint(1, 1e30) #生成指定范围内的随机整数 >>> x 839746558215897242220046223150 >>> list(map(int, str(x))) #提取大整数每位上的数字 [8, 3, 9, 7, 4, 6, 5, 5, 8, 2, 1, 5, 8, 9, 7, 2, 4, 2, 2, 2, 0, 0, 4, 6, 2, 2, 3, 1, 5, 0]

(2)reduce()。标准库functools中的函数reduce()可以将一个接收2个参数的函数以迭代累积的方式从左到右依次作用到一个序列或迭代器对象的所有元素上,并且允许指定一个初始值。例如,reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])计算过程为((((1+2)+3)+4)+5),第一次计算时x为1而y为2,再次计算时x的值为(1+2)而y的值为3,再次计算时x的值为((1+2)+3)而y的值为4,以此类推,最终完成计算并返回((((1+2)+3)+4)+5)的值。 >>> from functools import reduce >>> seq = list(range(1, 10)) >>> reduce(add, seq) #add是上一段代码中定义的函数 45 >>> reduce(lambda x, y: x+y, seq) #使用lambda表达式实现相同功能 45

上面这两段代码的功能是一样的,执行过程如下图:

>>> import operator #标准库operator提供了大量运算 >>> operator.add(3,5) #可以像普通函数一样直接调用 8 >>> reduce(operator.add, seq) #使用add运算 45 >>> reduce(operator.add, seq, 5) #指定累加的初始值为5 50 >>> reduce(operator.mul, seq) #乘法运算 362880 >>> reduce(operator.mul, range(1, 6)) #5的阶乘 120 >>> reduce(operator.add, map(str, seq)) #转换成字符串再累加 '123456789' >>> ''.join(map(str, seq)) #使用join()方法实现字符串连接 '123456789' >>> reduce(operator.add, [[1, 2], [3], [4]], []) #这个操作占用空间较大,慎用 [1, 2, 3, 4]

与上面代码中最后演示的用法类似,作为一种技巧,reduce()函数还支持下面的用法(感谢浙江省浦江中学方春林老师提供本例用法): >>> from random import randint >>> lst = [randint(1, 10) for i in range(50)] #随机数列表 >>> def tjNum(dic, k): #统计元素出现次数 if k in dic: dic[k] += 1 else: dic[k] = 1 return dic

>>> from functools import reduce >>> reduce(tjNum, lst, {}) {1: 6, 2: 3, 3: 6, 4: 3, 5: 4, 6: 7, 7: 5, 8: 5, 9: 6, 10: 5}

(3)filter()。内置函数filter()将一个单参数函数作用到一个序列上,返回该序列中使得该函数返回值为True的那些元素组成的filter对象,如果指定函数为None,则返回序列中等价于True的元素。 >>> seq = ['foo', 'x41', '?!', '***'] >>> def func(x): return x.isalnum() #测试是否为字母或数字 >>> filter(func, seq) #返回filter对象 <filter object at 0x000000000305D898> >>> list(filter(func, seq)) #把filter对象转换为列表 ['foo', 'x41'] >>> [x for x in seq if x.isalnum()] #使用列表推导式实现相同功能 ['foo', 'x41'] >>> list(filter(lambda x: x.isalnum(), seq)) #使用lambda表达式实现相同功能 ['foo', 'x41'] >>> list(filter(None, [1, 2, 3, 0, 0, 4, 0, 5])) #指定函数为None [1, 2, 3, 4, 5]

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python小屋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档