跟老齐学Python之大话题小函数(2)

上一讲和本讲的标题是“大话题小函数”,所谓大话题,就是这些函数如果溯源,都会找到听起来更高大上的东西。这种思维方式绝对我坚定地继承了中华民族的优良传统的。自从天朝的臣民看到英国人开始踢足球,一直到现在所谓某国勃起了,都一直在试图论证足球起源于该朝的前前前朝的某国时代,并且还搬出了那时候的一个叫做高俅的球星来论证,当然了,勃起的某国是挡不住该国家队在世界杯征程上的阳痿,只能用高俅来意淫一番了。这种思维方式,我是坚定地继承,因为在我成长过程中,它一直被奉为优良传统。阿Q本来是姓赵的,和赵老爷是本家,比秀才要长三辈,虽然被赵老爷打了嘴。

废话少说,书接前文,已经研究了map,下面来看reduce。

忍不住还得来点废话。不知道看官是不是听说过MapReduc,如果没有,那么Hadoop呢?如果还没有,就google一下。下面是我从维基百科上抄下来的,共赏之。

代码如下:

MapReduce是Google提出的一个软件架构,用于大规模数据集(大于1TB)的并行运算。概念“Map(映射)”和“Reduce(化简)”,及他们的主要思想,都是从函数式编程语言借来的,还有从矢量编程语言借来的特性。

不用管是不是看懂,总之又可以用开头的思想意淫一下了,原来今天要鼓捣的这个reduce还跟大数据有关呀。不管怎么样,你有梦一般的感觉就行。

reduce

回到现实,清醒一下,继续敲代码:

代码如下:

>>> reduce(lambda x,y: x+y,[1,2,3,4,5])
15

请看官仔细观察,是否能够看出是如何运算的呢?画一个图:

还记得map是怎么运算的吗?忘了?看代码:

代码如下:

>>> list1 = [1,2,3,4,5,6,7,8,9]
>>> list2 = [9,8,7,6,5,4,3,2,1]
>>> map(lambda x,y: x+y, list1,list2)
[10, 10, 10, 10, 10, 10, 10, 10, 10]

看官对比一下,就知道两个的区别了。原来map是上下运算,reduce是横着逐个元素进行运算。

权威的解释来自官网:

代码如下:

reduce(function, iterable[, initializer])
 
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:

代码如下:

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 it:
        accum_value = function(accum_value, x)   
    return accum_value

如果用我们熟悉的for循环来做上面reduce的事情,可以这样来做:

代码如下:

>>> lst = range(1,6)
>>> lst
[1, 2, 3, 4, 5]
>>> r = 0
>>> for i in range(len(lst)):
...     r += lst[i]
...
>>> r
15

for普世的,reduce是简洁的。

为了锻炼思维,看这么一个问题,有两个list,a = [3,9,8,5,2],b=[1,4,9,2,6],计算:a[0]b[0]+a1b1+...的结果。

代码如下:

>>> a
[3, 9, 8, 5, 2]
>>> b
[1, 4, 9, 2, 6]

>>> zip(a,b)        #复习一下zip,下面的方法中要用到
[(3, 1), (9, 4), (8, 9), (5, 2), (2, 6)]

>>> sum(x*y for x,y in zip(a,b))    #解析后直接求和
133

>>> new_list = [x*y for x,y in zip(a,b)]    #可以看做是上面方法的分布实施
>>> #这样解析也可以:new_tuple = (x*y for x,y in zip(a,b))
>>> new_list
[3, 36, 72, 10, 12]
>>> sum(new_list)     #或者:sum(new_tuple)
133

>>> reduce(lambda sum,(x,y): sum+x*y,zip(a,b),0)    #这个方法是在耍酷呢吗?
133

>>> from operator import add,mul            #耍酷的方法也不止一个
>>> reduce(add,map(mul,a,b))
133

>>> reduce(lambda x,y: x+y, map(lambda x,y: x*y, a,b))  #map,reduce,lambda都齐全了,更酷吗?
133

 filter

filter的中文含义是“过滤器”,在python中,它就是起到了过滤器的作用。首先看官方说明:

代码如下:

filter(function, iterable)

Construct a list from those elements of iterable for which function returns true. iterable may be either a sequence, a container which supports iteration, or an iterator. If iterable is a string or a tuple, the result also has that type; otherwise it is always a list. If function is None, the identity function is assumed, that is, all elements of iterable that are false are removed.

Note that filter(function, iterable) is equivalent to [item for item in iterable if function(item)] if function is not None and [item for item in iterable if item] if function is None.

这次真的不翻译了(好像以往也没有怎么翻译呀),而且也不解释要点了。请列位务必自己阅读上面的文字,并且理解其含义。英语,无论怎么强调都是不过分的,哪怕是做乞丐,说两句英语,没准还可以讨到英镑美元呢。

通过下面代码体会:

代码如下:

>>> numbers = range(-5,5)
>>> numbers
[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]

>>> filter(lambda x: x>0, numbers)
[1, 2, 3, 4]

>>> [x for x in numbers if x>0]     #与上面那句等效
[1, 2, 3, 4]

>>> filter(lambda c: c!='i', 'qiwsir')  #能不能对应上面文档说明那句话呢?
'qwsr'                                  #“If iterable is a string or a tuple, the result also has that type;”

至此,用两此介绍了几个小函数,这些函数在对程序的性能提高上,并没有显著或者稳定预期,但是,在代码的简洁上,是有目共睹的。有时候是可以用来秀一秀,彰显python的优雅和自己耍酷。

(0)

相关推荐

  • 跟老齐学Python之关于类的初步认识

    在开始部分,请看官非常非常耐心地阅读下面几个枯燥的术语解释,本来这不符合本教程的风格,但是,请看官谅解,因为列位将来一定要阅读枯燥的东西的.这些枯燥的属于解释,均来自维基百科. 1.问题空间 问题空间是问题解决者对一个问题所达到的全部认识状态,它是由问题解决者利用问题所包含的信息和已贮存的信息主动地构成的. 一个问题一般有下面三个方面来定义:  •初始状态--一开始时的不完全的信息或令人不满意的状况:  •目标状态--你希望获得的信息或状态:  •操作--为了从初始状态迈向目标状态,你可能采取的

  • 跟老齐学Python之传说中的函数编写条规

    关于函数的事情,总是说不完的,下面就罗列一些编写函数的注意事项.特别声明,这些事项不是我总结的,我是从一本名字为<Learning Python>的书里面抄过来的,顺便写成了汉语,当然,是按照自己的视角翻译的,里面也夹杂了一些自己的观点.看官也可以理解为源于<Learning Python>但又有点儿不同.  •函数具有独立性.也就是常说的不要有太强的耦合性.要让函数能够独立于外部的东西.参数和return语句就是实现这种独立性的最好方法.  •尽量不要使用全局变量,这也是让函数具

  • 跟老齐学Python之让人欢喜让人忧的迭代

    哦,这就是真正牛X的程序员.不过,他也仅仅是牛X罢了,还不是大神.大神程序员是什么样儿呢?他是扫地僧,大隐隐于市. 先搞清楚这些名词再说别的: 循环(loop),指的是在满足条件的情况下,重复执行同一段代码.比如,while语句. 迭代(iterate),指的是按照某种顺序逐个访问列表中的每一项.比如,for语句. 递归(recursion),指的是一个函数不断调用自身的行为.比如,以编程方式输出著名的斐波纳契数列. 遍历(traversal),指的是按照一定的规则访问树形结构中的每个节点,而且

  • 跟老齐学Python之总结参数的传递

    就前面所讲,函数的基本内容已经完毕.但是,函数还有很多值得不断玩味的细节.这里进行阐述. 参数的传递 python中函数的参数通过赋值的方式来传递引用对象.下面总结通过总结常见的函数参数定义方式,来理解参数传递的流程. def foo(p1,p2,p3,...) 这种方式最常见了,列出有限个数的参数,并且彼此之间用逗号隔开.在调用函数的时候,按照顺序以此对参数进行赋值,特备注意的是,参数的名字不重要,重要的是位置.而且,必须数量一致,一一对应.第一个对象(可能是数值.字符串等等)对应第一个参数,

  • 跟老齐学Python之Python文档

    文档很重要.独孤九剑的剑诀.易筋经的心法.写着辟邪剑谱的袈裟,这些都是文档.连那些大牛人都要这些文档,更何况我们呢?所以,文档是很重要的. 文档,说白了就是用word(这个最多了)等(注意这里的等,把不常用的工具都等掉了,包括我编辑文本时用的vim工具)文本编写工具写成的包含文本内容但不限于文字的文件.有点啰嗦,啰嗦的目的是为了严谨,呵呵.最好还是来一个更让人信服的定义,当然是来自维基百科. 复制代码 代码如下: 软件文档或者源代码文档是指与软件系统及其软件工程过程有关联的文本实体.文档的类型包

  • 跟老齐学Python之变量和参数

    那么什么这两个到底有什么区别和联系呢?我在网上搜了一下,发现很多说法,虽然大同小异,但是似乎只有下面这一段来自微软网站的比较高度抽象,而且意义涵盖深远.我摘抄过来,看官读一读,是否理解,虽然是针对VB而言的,一样有启发. 复制代码 代码如下: 参数和变量之间的差异 (Visual Basic) 多数情况下,过程必须包含有关调用环境的一些信息.执行重复或共享任务的过程对每次调用使用不同的信息.此信息包含每次调用过程时传递给它的变量.常量和表达式. 若要将此信息传递给过程,过程先要定义一个形参,然后

  • 跟老齐学Python之重回函数

    函数的基本结构 Python中的函数基本结构: 复制代码 代码如下: def 函数名([参数列表]):     语句 几点说明:  •函数名的命名规则要符合python中的命名要求.一般用小写字母和单下划线.数字等组合  •def是函数的开始,这个简写来自英文单词define,显然,就是要定义一个什么东西  •函数名后面是圆括号,括号里面,可以有参数列表,也可以没有参数  •千万不要忘记了括号后面的冒号  •语句,相对于def缩进,按照python习惯,缩进四个空格 看简单例子,深入理解上面的要

  • 跟老齐学Python之大话题小函数(1)

    开篇就要提到一个大的话题:编程范型.什么是编程范型?引用维基百科中的解释: 复制代码 代码如下: 编程范型或编程范式(英语:Programming paradigm),(范即模范之意,范式即模式.方法),是一类典型的编程风格,是指从事软件工程的一类典型的风格(可以对照方法学).如:函数式编程.程序编程.面向对象编程.指令式编程等等为不同的编程范型. 编程范型提供了(同时决定了)程序员对程序执行的看法.例如,在面向对象编程中,程序员认为程序是一系列相互作用的对象,而在函数式编程中一个程序会被看作是

  • 跟老齐学Python之大话题小函数(2)

    上一讲和本讲的标题是"大话题小函数",所谓大话题,就是这些函数如果溯源,都会找到听起来更高大上的东西.这种思维方式绝对我坚定地继承了中华民族的优良传统的.自从天朝的臣民看到英国人开始踢足球,一直到现在所谓某国勃起了,都一直在试图论证足球起源于该朝的前前前朝的某国时代,并且还搬出了那时候的一个叫做高俅的球星来论证,当然了,勃起的某国是挡不住该国家队在世界杯征程上的阳痿,只能用高俅来意淫一番了.这种思维方式,我是坚定地继承,因为在我成长过程中,它一直被奉为优良传统.阿Q本来是姓赵的,和赵老

  • 跟老齐学Python之做一个小游戏

    在讲述有关list的时候,提到做游戏的事情,后来这个事情一直没有接续.不是忘记了,是在想在哪个阶段做最合适.经过一段时间学习,看官已经不是纯粹小白了,已经属于python初级者了.现在就是开始做那个游戏的时候了. 游戏内容:猜数字游戏 太简单了吧.是的,游戏难度不大,不过这个游戏中蕴含的东西可是值得玩味的. 游戏过程描述 程序运行起来,随机在某个范围内选择一个整数. 提示用户输入数字,也就是猜程序随即选的那个数字. 程序将用户输入的数字与自己选定的对比,一样则用户完成游戏,否则继续猜. 使用次数

  • 跟老齐学Python之玩转字符串(1)

    如果对自然语言分类,有很多中分法,比如英语.法语.汉语等,这种分法是最常见的.在语言学里面,也有对语言的分类方法,比如什么什么语系之类的.我这里提出一种分法,这种分法尚未得到广大人民群众和研究者的广泛认同,但是,我相信那句"真理是掌握在少数人的手里",至少在这里可以用来给自己壮壮胆. 我的分法:一种是语言中的两个元素(比如两个字)和在一起,出来一个新的元素(比如新的字):另外一种是两个元素和在一起,知识两个元素并列.比如"好"和"人",两个元素和

  • 跟老齐学Python之深入变量和引用对象

    在<永远强大的函数>那一讲中,老齐我已经向看官们简述了一下变量,之后我们就一直在使用变量,每次使用变量,都要有一个操作,就是赋值.本讲再次提及这个两个事情,就是要让看官对变量和赋值有一个知其然和知其所以然的认识.当然,最后能不能达到此目的,主要看我是不是说的通俗易懂了.如果您没有明白,就说明我说的还不够好,可以联系我,我再为您效劳. 变量和对象 在<learning python>那本书里面,作者对变量.对象和引用的关系阐述的非常明了.我这里在很大程度上是受他的启发.感谢作者Mar

  • 跟老齐学Python之坑爹的字符编码

    字符编码,在编程中,是一个让学习者比较郁闷的东西,比如一个str,如果都是英文,好说多了.但恰恰不是如此,中文是我们不得不用的.所以,哪怕是初学者,都要了解并能够解决字符编码问题. >>> name = '老齐' >>> name '\xe8\x80\x81\xe9\xbd\x90' 在你的编程中,你遇到过上面的情形吗?认识最下面一行打印出来的东西吗?看人家英文,就好多了 >>> name = "qiwsir" >>&g

  • 跟老齐学Python之Python安装

    任何高级语言都是需要一个自己的编程环境的,这就好比写字一样,需要有纸和笔,在计算机上写东西,也需要有文字处理软件,比如各种名称的OFFICE.笔和纸以及office软件,就是写东西的硬件或软件,总之,那些文字只能写在那个上边,才能最后成为一篇文章.那么编程也是,要有个什么程序之类的东西,要把程序写到那个上面,才能形成最后类似文章那样的东西. 刚才又有了一个术语--"程序",什么是程序?本文就不讲了.如果列为观众不是很理解这个词语,请上网google一下. 注:推荐一种非常重要的学习方法

  • 跟老齐学Python之使用Python查询更新数据库

    回顾一下已有的战果:(1)连接数据库;(2)建立指针:(3)通过指针插入记录:(4)提交将插入结果保存到数据库.在交互模式中,先温故,再知新. 复制代码 代码如下: >>> #导入模块 >>> import MySQLdb >>> #连接数据库 >>> conn = MySQLdb.connect(host="localhost",user="root",passwd="123123&

  • 跟老齐学Python之玩转字符串(3)

    字符串就是一个话题中心. 给字符串编号 在很多很多情况下,我们都要对字符串中的每个字符进行操作(具体看后面的内容),要准确进行操作,必须做的一个工作就是把字符进行编号.比如一个班里面有50名学生,如果这些学生都有学号,老师操作他们将简化很多.比如不用专门找每个人名字,直接通过学号知道谁有没有交作业. 在python中按照这样的顺序对字符串进行编号:从左边第一个开始是0号,向下依次按照整数增加,为1.2...,直到最后一个,在这个过程中,所有字符,包括空格,都进行变好.例如: Hello,wor

  • 跟老齐学Python之永远强大的函数

    函数,对于人类来讲,能够发展到这个数学思维层次,是一个飞跃.可以说,它的提出,直接加快了现代科技和社会的发展,不论是现代的任何科技门类,乃至于经济学.政治学.社会学等,都已经普遍使用函数. 下面一段来自维基百科(在本教程中,大量的定义来自维基百科,因为它真的很百科):函数词条 函数这个数学名词是莱布尼兹在1694年开始使用的,以描述曲线的一个相关量,如曲线的斜率或者曲线上的某一点.莱布尼兹所指的函数现在被称作可导函数,数学家之外的普通人一般接触到的函数即属此类.对于可导函数可以讨论它的极限和导数

随机推荐