Maison > Article > développement back-end > 跟老齐学Python之让人欢喜让人忧的迭代
哦,这就是真正牛X的程序员。不过,他也仅仅是牛X罢了,还不是大神。大神程序员是什么样儿呢?他是扫地僧,大隐隐于市。
先搞清楚这些名词再说别的:
循环(loop),指的是在满足条件的情况下,重复执行同一段代码。比如,while语句。
迭代(iterate),指的是按照某种顺序逐个访问列表中的每一项。比如,for语句。
递归(recursion),指的是一个函数不断调用自身的行为。比如,以编程方式输出著名的斐波纳契数列。
遍历(traversal),指的是按照一定的规则访问树形结构中的每个节点,而且每个节点都只访问一次。
对于这四个听起来高深莫测的词汇,在教程中,已经涉及到了一个——循环(loop),本经主要介绍一下迭代(iterate),看官在网上google,就会发现,对于迭代和循环、递归之间的比较的文章不少,分别从不同角度将它们进行了对比。这里暂不比较,先搞明白python中的迭代。之后适当时机再比较,如果我不忘记的话,哈哈。
逐个访问
在python中,访问对象中每个元素,可以这么做:(例如一个list)
除了这种方法,还可以这样:
做为一名优秀的程序员,最佳品质就是“懒惰”,当然不能这样一个一个地敲啦,于是就:
>>> lst_iter = iter(lst) #那就再写一遍,上面的错误暂且搁置,回头在研究
>>> while True:
... print lst_iter.next()
...
q #果然自动化地读取了
i
w
s
i
r
Traceback (most recent call last): #读取到最后一个之后,报错,停止循环
File "
StopIteration
>>>
首先了解一下上面用到的那个内置函数:iter(),官方文档中有这样一段话描述之:
大意是说...(此处故意省略若干字,因为我相信看此文章的看官英语水平是达到看文档的水平了,乳沟没有,也不用着急,找个词典什么的帮助一下。)
尽管不翻译了,但是还要提炼一下主要的东西:
返回值是一个迭代器对象
参数需要是一个符合迭代协议的对象或者是一个序列对象
next()配合与之使用
什么是“可迭代的对象”呢?一般,我们常常将哪些能够用for来一个一个读取元素的对象,就称之为可迭代的对象。那么for也就被称之为迭代工具。所谓迭代工具,就是能够按照一定顺序扫描迭代对象的每个元素(按照从左到右的顺序),显然,除了for之外,还有别的可以称作迭代工具,比如列表解析,in来判断某元素是否属于序列对象等。
那么,刚才介绍的iter()的功能呢?它与next()配合使用,也是实现上述迭代工具的作用。在python中,甚至在其它的语言中,迭代这块的说法比较乱,主要是名词乱,刚才我们说,那些能够实现迭代的东西,称之为迭代工具,就是这些迭代工具,不少程序员都喜欢叫做迭代器。当然,这都是汉语翻译,英语就是iterator。
看官看上面的所有例子会发现,如果用for来迭代,当到末尾的时候,就自动结束了,不会报错。如果用iter()...next()迭代,当最后一个完成之后,它不会自动结束,还要向下继续,但是后面没有元素了,于是就报一个称之为StopIteration的错误(这个错误的名字叫做:停止迭代,这哪里是报错,分明是警告)。
看官还要关注iter()...next()迭代的一个特点。当迭代对象lst_iter被迭代结束,即每个元素都读取一边之后,指针就移动到了最后一个元素的后面。如果再访问,指针并没有自动返回到首位置,而是仍然停留在末位置,所以报StopIteration,想要再开始,需要重新再入迭代对象。所以,列位就看到,当我在上面重新进行迭代对象赋值之后,又可以继续了。这在for等类型的迭代工具中是没有的。
文件迭代器
现在有一个文件,名称:208.txt,其内容如下:
用迭代器来操作这个文件,我们在前面讲述文件有关知识的时候已经做过了,无非就是:
以上演示的是用readline()一行一行地读。当然,在实际操作中,我们是绝对不能这样做的,一定要让它自动进行,比较常用的方法是:
这段代码之所没有打印出东西来,是因为经过前面的迭代,指针已经移到了最后了。这就是迭代的一个特点,要小心指针的位置。
这种方法是读取文件常用的。另外一个readlines()也可以。但是,需要有一些小心的地方,看官如果想不起来小心什么,可以在将关于文件的课程复习一边。
上面过程用next()也能够读取。
如果用next(),就可以直接读取每行的内容。这说明文件是天然的可迭代对象,不需要用iter()转换了。
再有,我们用for来实现迭代,在本质上,就是自动调用next(),只不过这个工作,已经让for偷偷地替我们干了,到这里,列位是不是应该给for取另外一个名字:它叫雷锋。
前面提到了,列表解析也能够做为迭代工具,在研究列表的时候,看官想必已经清楚了。那么对文件,是否可以用?试一试:
至此,看官难道还不为列表解析所折服吗?真的很强大,又强又大呀。
其实,迭代器远远不止上述这么简单,下面我们随便列举一些,在python中还可以这样得到迭代对象中的元素。
>>> 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()手动一步一步迭代)。