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

哦,这就是真正牛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

做为一名优秀的程序员,最佳品质就是“懒惰”,当然不能这样一个一个地敲啦,于是就:

代码如下:

>>> 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也就被称之为迭代工具。所谓迭代工具,就是能够按照一定顺序扫描迭代对象的每个元素(按照从左到右的顺序),显然,除了for之外,还有别的可以称作迭代工具,比如列表解析,in来判断某元素是否属于序列对象等。

那么,刚才介绍的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()手动一步一步迭代)。

(0)

相关推荐

  • python使用三角迭代计算圆周率PI的方法

    本文实例讲述了python使用三角迭代计算圆周率PI的方法.分享给大家供大家参考.具体如下: 方法1: 复制代码 代码如下: # Calculating PI using trigonometric iterations # FB36 - 20130825 import math x = 1.0 y = 1.0 z = 1.0 w = 1.0 v = 1.0 u = 1.0 for i in range(30):       x = math.sin(x) + x     y = math.co

  • python迭代器的使用方法实例

    什么是迭代器? 迭代器是带有next方法的简单对象,当然也要实现__iter__函数.迭代器能在一序列的值上进行迭代,当没有可供迭代时,next方法就会引发StopIteration 的异常.python中有很多的对象都是迭代器,例如:列表,元素,字符串,文件,映射,集合 如何使用迭代器? 1. for 变量 in 可迭代对象 复制代码 代码如下: list1 = [1,2,3,4,5] for ele in list1:    print ele, 结果为:1 2 3 4 5 2. if 变量

  • Python专用方法与迭代机制实例分析

    本文实例讲述了Python专用方法与迭代机制,分享给大家供大家参考之用.具体分析如下: 众所周知,Python 设计哲学是"优雅"."明确"."简单",对于一件事只用一种最好的方法来做,而这种优雅在于背后很自然的隐藏了很多细节.比如对一些对象直接用for 语句来迭代,一些全局函数可以作用于很多具有共同特征的对象,还有生成器装饰器自省等特性.其中很多实现都是借助 Python  内部专用方法,而对外则使用统一的全局函数来进行操作,在配合一些语法糖,

  • Python迭代用法实例教程

    本文实例讲述了Python中迭代的用法,是一个非常实用的技巧.分享给大家供大家参考借鉴之用.具体分析如下: 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们成为迭代(Iteration). 在Python中,迭代是通过for ... in来完成的,而很多语言比如C或者Java,迭代list是通过下标完成的,比如Java代码: for (i=0; i<list.length; i++) { n = list[i]; } 可以看出,Python的f

  • Python中对象迭代与反迭代的技巧总结

    一.如何实现可迭代对象和迭代器对象? 实际案例 某软件要求从网络抓取各个城市气味信息,并其次显示: 北京: 15 ~ 20 天津: 17 ~ 22 长春: 12 ~ 18 ...... 如果一次抓取所有城市天气再显示,显示第一个城市气温时,有很高的延时,并且浪费存储空间,我们期望以用时访问的策略,并且把所有城市气温封装到一个对象里,可用for语句进行迭代,如何解决? 解决方案 实现一个迭代器对象Weatherlterator,next方法每次返回一个城市气温,实现一个可迭代对象Weatherlt

  • 深入解析Python中的list列表及其切片和迭代操作

    有序列表list >>> listTest = ['ha','test','yes'] >>> listTest ['ha', 'test', 'yes'] len()获取list元素个数. >>> len(listTest) 3 可以用索引来访问每一个元素,0表示第一个,-1还可以表示最后一个,即倒数第一个,依此类推-2表示倒数第二个,超过了也会报越界错误. >>> listTest[0] 'ha' >>> lis

  • python的迭代器与生成器实例详解

    本文以实例详解了python的迭代器与生成器,具体如下所示: 1. 迭代器概述:   迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.   1.1 使用迭代器的优点   对于原生支持随机访问的数据结构(如tuple.list),迭代器和经典for循环的索引访问相比并无优势,反而丢失了索引值(可以使用内建函数enumerate()找回这个索引值).但对于无法随机访问的数据结构(比

  • python计算牛顿迭代多项式实例分析

    本文实例讲述了python计算牛顿迭代多项式的方法.分享给大家供大家参考.具体实现方法如下: ''' p = evalPoly(a,xData,x). Evaluates Newton's polynomial p at x. The coefficient vector 'a' can be computed by the function 'coeffts'. a = coeffts(xData,yData). Computes the coefficients of Newton's po

  • 深入讲解Python中的迭代器和生成器

    在Python中,很多对象都是可以通过for语句来直接遍历的,例如list.string.dict等等,这些对象都可以被称为可迭代对象.至于说哪些对象是可以被迭代访问的,就要了解一下迭代器相关的知识了. 迭代器 迭代器对象要求支持迭代器协议的对象,在Python中,支持迭代器协议就是实现对象的__iter__()和next()方法.其中__iter__()方法返回迭代器对象本身:next()方法返回容器的下一个元素,在结尾时引发StopIteration异常. __iter__()和next()

  • python中迭代器(iterator)用法实例分析

    本文实例讲述了python中迭代器(iterator)用法.分享给大家供大家参考.具体如下: #--------------------------------------- # Name: iterators.py # Author: Kevin Harris # Last Modified: 03/11/04 # Description: This Python script demonstrates how to use iterators. #----------------------

随机推荐