你竟任着刚硬不悔改的心,为本身积蓄忿怒,以至神震怒,显他公义审判的日子来到。他必照各人的行为报应各人。凡恒心行善,寻求荣耀、尊贵和不能朽坏之福的,就以永生报应他们;唯有结党不顺从真理,反顺从不义的,就以忿怒、恼恨报应他们。(ROMANS 2:7-8)
迭代
跟一些比较牛X的程序员交流,常常听到他们嘴里冒出一个不标准的英文单词,而loop、iterate、traversal和recursion若是不在其内,总以为他还不够牛X。当让,真正牛X的绝对不会这么说的,他们只是说“循环、迭代、遍历、递归”,而后再问“这个你懂吗?”。哦,这就是真正牛X的程序员。不过,他也仅仅是牛X罢了,还不是大神。大神程序员是什么样儿呢?他是扫地僧,大隐隐于市。
循环(loop),指的是在知足条件的状况下,重复执行同一段代码。好比,while语句。
迭代(iterate),指的是按照某种顺序逐个访问列表中的每一项。好比,for语句。
递归(recursion),指的是一个函数不断调用自身的行为。好比,以编程方式输出著名的斐波纳契数列。
遍历(traversal),指的是按照必定的规则访问树形结构中的每一个节点,并且每一个节点都只访问一次。
对于这四个听起来高深莫测的词汇,其实前面,已经涉及到了一个——循环(loop),本节主要介绍一下迭代(iterate),看官在网上google,就会发现,对于迭代和循环、递归之间的比较的文章很多,分别从不一样角度将它们进行了对比。这里暂不比较,先搞明白python中的迭代。
固然,迭代的话题若是要提及来,会很长,本着按部就班的原则,这里介绍比较初级的。
逐个访问
在python中,访问对象中每一个元素,能够这么作:(例如一个list)
>>> lst
['q', 'i', 'w', 's', 'i', 'r']
>>> for i in lst:
... print i,
...
q i w s i r
除了这种方法,还能够这样:
>>> lst_iter = iter(lst) #对原来的list实施了一个iter()
>>> lst_iter.next() #要不厌其烦地一个一个手动访问
'q'
>>> lst_iter.next()
'i'
>>> lst_iter.next()
'w'
>>> lst_iter.next()
's'
>>> lst_iter.next()
'i'
>>> lst_iter.next()
'r'
>>> lst_iter.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
iter()是一个内建函数,其含义是:
上面的next()就是要得到下一个元素,可是作为一名优秀的程序员,最佳品质就是“懒惰”,固然不能这样一个一个地敲啦,因而就:
>>> while True:
... print lst_iter.next()
...
Traceback (most recent call last): #竟然报错,并且错误跟前面同样?什么缘由
File "<stdin>", line 2, in <module>
StopIteration
先无论错误,再来一遍。
>>> lst_iter = iter(lst) #上面的错误暂且搁置,回头在研究
>>> while True:
... print lst_iter.next()
...
q #果真自动化地读取了
i
w
s
i
r
Traceback (most recent call last): #读取到最后一个以后,报错,中止循环
File "<stdin>", line 2, in <module>
StopIteration
首先了解一下上面用到的那个内置函数:iter(),官方文档中有这样一段话描述之:
iter(o[, sentinel])
Return an iterator object. The first argument is interpreted very differently depending on the presence of the second argument. Without a second argument, o must be a collection object which supports the iteration protocol (the iter() method), or it must support the sequence protocol (the getitem() method with integer arguments starting at 0). If it does not support either of those protocols, TypeError is raised. If the second argument, sentinel, is given, then o must be a callable object. The iterator created in this case will call o with no arguments for each call to its next() method; if the value returned is equal to sentinel, StopIteration will be raised, otherwise the value will be returned.
大意是说...(此处故意省略若干字,由于我相信看此文章的看官英语水平是达到看文档的水平了,若是没有,也不用着急,找个词典什么的帮助一下。)
尽管不翻译了,可是还要提炼一下主要的东西:
返回值是一个迭代器对象
参数须要是一个符合迭代协议的对象或者是一个序列对象
next()配合与之使用
什么是“可迭代的对象”呢?在前面学习的时候,曾经提到过,若是忘记了请往前翻阅。
通常,咱们经常将哪些可以用诸如循环语句之类的方法来一个一个读取元素的对象,就称之为可迭代的对象。那么用来循环的如for就被称之为迭代工具。
用严格点的语言说:所谓迭代工具,就是可以按照必定顺序扫描迭代对象的每一个元素(按照从左到右的顺序)。
显然,除了for以外,还有别的能够称做迭代工具。
那么,刚才介绍的iter()的功能呢?它与next()配合使用,也是实现上述迭代工具的做用。
在python中,甚至在其它的语言中,迭代这块的说法比较乱,主要是名词乱,刚才咱们说,那些可以实现迭代的东西,称之为迭代工具,就是这些迭代工具,很多程序员都喜欢叫作迭代器。固然,这都是汉语翻译,英语就是iterator。
看官看上面的全部例子会发现,若是用for来迭代,当到末尾的时候,就自动结束了,不会报错。若是用iter()...next()迭代,当最后一个完成以后,它不会自动结束,还要向下继续,可是后面没有元素了,因而就报一个称之为StopIteration的错误(这个错误的名字叫作:中止迭代,这哪里是报错,分明是警告)。
看官还要关注iter()...next()迭代的一个特色。当迭代对象lst_iter被迭代结束,即每一个元素都读取了一遍以后,指针就移动到了最后一个元素的后面。若是再访问,指针并无自动返回到首位置,而是仍然停留在末位置,因此报StopIteration,想要再开始,须要从新载入迭代对象。因此,当我在上面从新进行迭代对象赋值以后,又能够继续了。这在for等类型的迭代工具中是没有的。
文件迭代器
如今有一个文件,名称:208.txt,其内容以下:
Learn python with qiwsir. There is free python course. The website is:

http://qiwsir.github.io Its language is Chinese.
用迭代器来操做这个文件,咱们在前面讲述文件有关知识的时候已经作过了,无非就是:
>>> f = open("208.txt")
>>> f.readline() #读第一行
'Learn python with qiwsir.\n'
>>> f.readline() #读第二行
'There is free python course.\n'
>>> f.readline() #读第三行
'The website is:\n'
>>> f.readline() #读第四行
'

http://qiwsir.github.io\n'
>>> f.readline() #读第五行,也就是这真在读完最后一行以后,到了此行的后面
'Its language is Chinese.\n'
>>> f.readline() #无内容了,可是不报错,返回空。
''
以上演示的是用readline()一行一行地读。固然,在实际操做中,咱们是绝对不能这样作的,必定要让它自动进行,比较经常使用的方法是:
>>> for line in f: #这个操做是紧接着上面的操做进行的,请看官主要观察
... print line, #没有打印出任何东西
...
这段代码之所没有打印出东西来,是由于通过前面的迭代,指针已经移到了最后了。这就是迭代的一个特色,要当心指针的位置。
>>> f = open("208.txt") #从头再来
>>> for line in f:
... print line,
...
Learn python with qiwsir.
There is free python course.
The website is:
http://qiwsir.github.io
Its language is Chinese.
这种方法是读取文件经常使用的。另一个readlines()也能够。可是,须要有一些当心的地方,看官若是想不起来当心什么,能够在将关于文件的课程复习一边。
上面过程用next()也可以读取。
>>> f = open("208.txt")
>>> f.next()
'Learn python with qiwsir.\n'
>>> f.next()
'There is free python course.\n'
>>> f.next()
'The website is:\n'
>>> f.next()
'

http://qiwsir.github.io\n'
>>> f.next()
'Its language is Chinese.\n'
>>> f.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
若是用next(),就能够直接读取每行的内容。这说明文件是自然的可迭代对象,不须要用iter()转换了。
再有,咱们用for来实现迭代,在本质上,就是自动调用next(),只不过这个工做,已经让for偷偷地替咱们干了,到这里,列位是否是应该给for取另一个名字:它叫雷锋。
还有,列表解析也可以作为迭代工具,在研究列表的时候,看官想必已经清楚了。那么对文件,是否能够用?试一试:
>>> [ line for line in open('208.txt') ]
['Learn python with qiwsir.\n', 'There is free python course.\n', 'The website is:\n', '

http://qiwsir.github.io\n', 'Its language is Chinese.\n']
至此,看官难道还不为列表解析所折服吗?真的很强大,又强又大呀。
其实,迭代器远远不止上述这么简单,下面咱们随便列举一些,在python中还能够这样获得迭代对象中的元素。
>>> list(open('208.txt'))
['Learn python with qiwsir.\n', 'There is free python course.\n', 'The website is:\n', '

http://qiwsir.github.io\n', 'Its language is Chinese.\n']
>>> tuple(open('208.txt'))
('Learn python with qiwsir.\n', 'There is free python course.\n', 'The website is:\n', '

http://qiwsir.github.io\n', 'Its language is Chinese.\n')
>>> "$$$".join(open('208.txt'))
'Learn python with qiwsir.\n$$$There is free python course.\n$$$The website is:\n$$$

http://qiwsir.github.io\n$$$Its language is Chinese.\n'
>>> a,b,c,d,e = open("208.txt")
>>> a
'Learn python with qiwsir.\n'
>>> b
'There is free python course.\n'
>>> c
'The website is:\n'
>>> d
'

http://qiwsir.github.io\n'
>>> e
'Its language is Chinese.\n' 上述方式,在编程实践中不必定用得上,只是向看官展现一下,而且看官要明白,能够这么作,不是非要这么作。 补充一下,字典也能够迭代,看官本身不妨摸索一下(其实前面已经用for迭代过了,此次请摸索一下用iter()...next()手动一步一步迭代)。