官方解释:

Apply function of two arguments cumulatively to the items of iterable, from left to right, so as to reduce the iterable to a single value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). The left argument, x, is the accumulated value and the right argument, y, is the update value from the iterable. If the optional initializer is present, it is placed before the items of the iterable in the calculation, and serves as a default when the iterable is empty. If initializer is not given and iterable contains only one item, the first item is returned. Roughly equivalent to:

意思就是说:将一个可迭代的对象应用到一个带有两个参数的方法上,我们称之为appFun,遍历这个可迭代对象,将其中的元素依次作为appFun的参数,但这个函数有两个参数,作为哪个参数呢?有这样的规则,看一下下面reduce方法的实现,有三个参数,第一个参数就是上面说的appFun,第二个参数就是那个可迭代的对象,而第三个呢?当调用reduce方法的时候给出了initializer这个参数,那么第一次调用appFun的时候这个参数值就作为第一个参数,而可迭代对象的元素依次作为appFun的第二个参数;如果调用reduce的时候没有给出initializer这个参数,那么第一次调用appFun的时候,可迭代对象的第一个元素就作为appFun的第一个元素,而可迭代器的从第二个元素到最后依次作为appFun的第二个参数,除第一次调用之外,appFun的第一个参数就是appFun的返回值了。例如reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]),计算1到5的和,因为没有给定initializer参数,所以第一次调用x+y时,x=1,即列表的第一个元素,y=2,即列表的第二个元素,之后返回的1+2的结果作为第二次调用x+y中的x,即上一次的结果,y=2,即第二个元素,依次类推,知道得到1+2+3+4+5的结果。

这样看来,其实下面的代码定义是有一点问题,我们在程序中调用这段代码reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]),得到的结果为16,而正确的结果为15,问题在于如果集合不是以0开始,那么按照如下代码,第一次调用x=1,即第一个元素,y也是等于1,也是第一个元素,而正确的y应该是2。所以真正的reduce方法应该和下面的例子是有差别的。

def reduce(function, iterable, initializer=None):
it = iter(iterable)
if initializer is None:
try:
initializer = next(it)
except StopIteration:
raise TypeError('reduce() of empty sequence with no initial value')
accum_value = initializer
for x in iterable:
accum_value = function(accum_value, x)
return accum_value

那么reduce函数能做什么,什么情况下要用reduce呢,看下面的例子:

例如上面的例子,实现一个整形集合的累加。假设lst = [1,2,3,4,5],实现累加的方式有很多:

第一种:用sum函数。

sum(lst)

第二种:循环方式。

def customer_sum(lst):
result = 0
for x in lst:
result+=x
return result #或者
def customer_sum(lst):
result = 0
while lst:
temp = lst.pop(0)
result+=temp
return result if __name__=="__main__":
lst = [1,2,3,4,5]
print customer_sum(lst)

第三种:递推求和

def add(lst,result):
if lst:
temp = lst.pop(0)
temp+=result
return add(lst,temp)
else:
return result if __name__=="__main__":
lst = [1,2,3,4,5]
print add(lst,0)

第四种:reduce方式

lst = [1,2,3,4,5]
print reduce(lambda x,y:x+y,lst)
#这种方式用lambda表示当做参数,因为没有提供reduce的第三个参数,所以第一次执行时x=1,y=2,第二次x=1+2,y=3,即列表的第三个元素 #或者
lst = [1,2,3,4,5]
print reduce(lambda x,y:x+y,lst,0)
#这种方式用lambda表示当做参数,因为指定了reduce的第三个参数为0,所以第一次执行时x=0,y=1,第二次x=0+1,y=2,即列表的第二个元素,
假定指定reduce的第三个参数为100,那么第一次执行x=100,y仍然是遍历列表的元素,最后得到的结果为115 #或者
def add(x,y):
return x+y print reduce(add, lst)
#与方式1相同,只不过把lambda表达式换成了自定义函数 #或者
def add(x,y):
return x+y print reduce(add, lst,0)
#与方式2相同,只不过把lambda表达式换成了自定义函数

再举一个例子:有一个序列集合,例如[1,1,2,3,2,3,3,5,6,7,7,6,5,5,5],统计这个集合所有键的重复个数,例如1出现了两次,2出现了两次等。大致的思路就是用字典存储,元素就是字典的key,出现的次数就是字典的value。方法依然很多

第一种:for循环判断

def statistics(lst):
dic = {}
for k in lst:
if not k in dic:
dic[k] = 1
else:
dic[k] +=1
return dic lst = [1,1,2,3,2,3,3,5,6,7,7,6,5,5,5]
print(statistics(lst))

第二种:比较取巧的,先把列表用set方式去重,然后用列表的count方法

def statistics2(lst):
m = set(lst)
dic = {}
for x in m:
dic[x] = lst.count(x) return dic lst = [1,1,2,3,2,3,3,5,6,7,7,6,5,5,5]
print statistics2(lst)

第三种:用reduce方式

def statistics(dic,k):
if not k in dic:
dic[k] = 1
else:
dic[k] +=1
return dic lst = [1,1,2,3,2,3,3,5,6,7,7,6,5,5,5]
print reduce(statistics,lst,{})
#提供第三个参数,第一次,初始字典为空,作为statistics的第一个参数,然后遍历lst,作为第二个参数,然后将返回的字典集合作为下一次的第一个参数 或者
d = {}
d.extend(lst)
print reduce(statistics,d)
#不提供第三个参数,但是要在保证集合的第一个元素是一个字典对象,作为statistics的第一个参数,遍历集合依次作为第二个参数

通过上面的例子发现,凡是要对一个集合进行操作的,并且要有一个统计结果的,能够用循环或者递归方式解决的问题,一般情况下都可以用reduce方式实现。

reduce函数真是“一位好同志啊”!

Python----reduce原来是这样用的的更多相关文章

  1. python reduce()函数

    reduce()函数 reduce()函数也是Python内置的一个高阶函数.reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传 ...

  2. python reduce使用实例

    通过一个简单的算法来了解reduce的巧用. 构建函数persistence(n),如果n>9,则返回0.否则继续根据n的权重来分解n,如n=999,则分解为9,9,9.那么将9*9*9=729 ...

  3. 弄明白python reduce 函数

    作者:Panda Fang 出处:http://www.cnblogs.com/lonkiss/p/understanding-python-reduce-function.html 原创文章,转载请 ...

  4. python reduce & map 习题

    基于廖雪峰教程作业 http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014317 ...

  5. py-day4-1 python reduce函数

    from functools import reduse    从模块中导入 reduce函数: 处理一个序列,然后把序列进行合并操作 #**** 问题:求1+2+3+100的和是多少? # 一,原始 ...

  6. python reduce和偏函数partial

    functools模块 reduce方法: reduce方法 reduce方法,顾名思义就是减少 可迭代对象不能为空,初始值没提供就在可迭代对象中去一个元素 from functools import ...

  7. python reduce()函数使用

    reduce()的使用方法形如reduce(function, iterable[, initializer]),它的形式和map()函数一样.不过参数f(x)必须有两个参数,initializer是 ...

  8. (转)Python函数式编程——map()、reduce()

    转自:http://www.jianshu.com/p/7fe3408e6048 1.map(func,seq1[,seq2...]) Python 函数式编程中的map()函数是将func作用于se ...

  9. python写mapReduce初步

    最近在学了python了,从mapReduce开始 ,话不多说了,直接上代码了哈 map阶段,map.py文件 import sys # 标准输入 # 在终端的话,就需要这样了 cat a.txt | ...

  10. 一起学Hadoop——使用IDEA编写第一个MapReduce程序(Java和Python)

    上一篇我们学习了MapReduce的原理,今天我们使用代码来加深对MapReduce原理的理解. wordcount是Hadoop入门的经典例子,我们也不能免俗,也使用这个例子作为学习Hadoop的第 ...

随机推荐

  1. 用maven在eclipse中创建Web项目

    使用eclipse插件创建一个web project 首先创建一个Maven的Project如下图 我们勾选上Create a simple project (不使用骨架) 这里的Packing 选择 ...

  2. 【ajax 提交表单】多种方式的注意事项

    在业务中,可能因为表单内容过于庞大,字段过于繁杂,如果人为去拼接的话 ,需要耗费大量的时间和精力,与此同时,代码看上去也是冗余不堪. 所以,提交表单的时候如果能整个表单数据整体提交,那是非常开心的事情 ...

  3. [RESTful]HTTP状态码

    HTTP状态码是一个依附于HTTP响应的3位数字,它是协议语义的一部分,能在最基本的层面上让客户端知道服务器在尝试处理请求的时候发生了什么事情.HTTP规范总共定义了41一个响应码,本文将对所有的状态 ...

  4. JAVABeanUtils

    在写如何使用java BeanUlits 之前需要清楚几件事情 1. 我们每次所定义的类,其实是实体,同时也被称作为JavaBean; 2.  为什么我们要使用BeanUlits这个框架     &g ...

  5. Git在window的使用(TortoiseGit)之一

    一.什么是Git? Git是分布式版本控制系统.它与SVN的主要区别:SVN在本地没有版本,不能脱机工作:Git是分布式控制系统,在自己的本地都有一个版本,可以脱机工作. 二.在window上安装Gi ...

  6. 关于UnsupportedClassVersionError的错误处理

    错误:Java.lang.UnsupportedClassVersionError: Bad version number in .class file 造成这种错误的原因是你的支持Tomcat运行的 ...

  7. docker入门-学习笔记

    docker可以类比成window下的VMware或者virtualbox软件.docker有两个基本的概念:容器(container)和镜像(image),分别对应为VMware中的系统镜像和系统镜 ...

  8. java运行时内存模式学习

    学习java运行时内存模式: 各区介绍: 方法区(线程共享):用于存放被虚拟机加载的类的元数据:静态变量,常量,以及编译和的代码(字节码),也称为永久代(所有该类的实例被回收,或者此类classLoa ...

  9. 【原】iOS学习之苹果原生代码实现Autolayout和VFL语言

    1.添加约束的规则 在创建约束之后,需要将其添加到作用的view上 在添加时要注意目标view需要遵循以下规则: 1)对于 两个同层级view之间 的约束关系,添加到它们的父view上 2)对于 两个 ...

  10. Ubuntu 树莓派2b交叉编译环境

    在一个平台上生成另一个平台上的可执行代码.为什么要大费周折的进行交叉编译呢?一句话:不得已而为之.有时是因为目的平台上不允许或不能够安装所需要的编译器,而又需要这个编译器的某些特征:有时是因为目的平台 ...