1. 可迭代对象
在高级语言中,迭代这一概念非常普遍。所谓迭代,就是依次遍历一个序列中的每个元素。而可迭代对象,就像一个容器,让你能够遍历它的所有元素。
常见的可迭代对象有列表、元组、字典、集合等。可迭代对象既可以是实际的序列,如列表,也可以是在迭代过程中一次产生一个元素的虚拟序列。
像列表这样的实际序列,是将全部的元素都保存在内存中,当元素个数较多时,内存占用比较大。而虚拟序列不同,它在迭代过程中即时给出当前元素的值,因此相比于实际的序列,虚拟序列占用的内存很小。
2. 迭代协议
Python中的迭代协议(Iteration Protocal),就是可迭代对象必须遵循的协议。当一个可迭代对象的 next
方法被调用时,会给出它的下一个元素,如果到达结果末尾,则触发 StopIteration
异常。
在Python中,可迭代对象必须具有 __iter__
方法,该方法通常返回对象本身,也可以返回其它可迭代对象。我们可以通过观察某个对象是否具有 __iter__
方法来判断它是否可以迭代。
注意:在 Python2.x 版本中,可迭代对象对应的方法是 next
,在 Python3.x 版本中,可迭代对象的方法是 __next__
。
3. 迭代器
可迭代对象可以通过Python内置函数 iter
来生成一个迭代器(iterator)。
例如,我们可以对列表使用该函数从而得到一个迭代器
>>> L = [1, 2, 3]
>>> I = iter(L)
>>> I.next()
1
>>> I.next()
2
>>> I.next()
3
>>> I.next()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
StopIteration
正如前面的迭代协议里提到的,当迭代器达到末尾时,便会触发 StopIteration
异常。
这是手动调用对象的 next
方法进行迭代的例子。但通常情况下,我们更多的是使用 for
循环语句来自动迭代。
>>> L = [1, 2, 3]
>>> for i in L:
... print i
>>> 1
>>> 2
>>> 3
for
循环语句在迭代时,自动调用了内置的 iter
来生成迭代器,省去了我们手动使用 iter(L)
生成迭代器这一步。
严格意义上讲,在Python中通过 iter
函数生成的对象叫做迭代器,而本身支持迭代的对象叫做可迭代对象。但在不引起误解的情况下,有时也把可迭代对象叫做迭代器。
4. 实现自己的迭代器
我们可以用类实现一个迭代器,在类中添加 next
方法和 __iter__
方法。
例如,我们实现一个类似于 xrange
的产生整数序列的迭代器:
class yrange:
def __init__(self, start=0, stop=0):
self.start = start
self.stop = stop
def __iter__(self):
return self
def next(self):
if(self.start < self.stop):
start = self.start
self.start += 1
return start
else:
raise StopIteration
运行结果如下
>>> for y in yrange(5, 8):
... print y
5
6
7
Python内置的一些函数如 list
、sum
、sorted
都支持迭代器作为参数,例如:
>>> list(yrange(1,4))
[1, 2, 3]
>>> sum(yrange(1, 4))
6
>>> sorted(yrange(1, 4), reverse=True)
[3, 2, 1]
5. 内置类型迭代器
在很多情况下,使用迭代器能够简化代码,还能够提高程序的性能,Python中有几种内置类型都具有其适用的迭代器。
5.1. 文件迭代器
读取文件时,我们经常使用文件对象的 readlines
方法。该方法实际上是返回一个列表,列表中存储了文件的每一行。
f = open('post.txt')
for line in f.readlines():
print line
使用这种方法来读取文件时,存在一个问题,就是内存占用较大。因为我们将文件内容一次性读取到了列表中,然后再迭代这个列表,这样效率会低一些。
实际上,当我们打开文件后,open
函数就返回了一个文件迭代器。文件迭代器是以C语言的速度执行的,因此速度更快,而且空间占用很小。
上面的代码改用文件迭代器的形式之后如下:
for line in open('post.txt'):
print line
非常简洁而且高效!
5.2. 字典迭代器
Python的字典有一个迭代器,在迭代时会一次返回一个键。
>>> D = {'a':1, 'b':2, 'c':3}
>>> for key in D:
... print key, D[key]
a 1
b 2
c 3
你也可以使用字典的 items
方法所返回的列表,只不过当字典比较大时,这种方法会占用较大空间。
>>> D = {'a':1, 'b':2, 'c':3}
>>> for key, value in D.items():
... print key, value
a 1
b 2
c 3
除此之外,元组、集合等类型都有自己的迭代器,这些类型的对象可以直接在迭代时使用。
参考文章:5. Iterators & Generators — Python Practice Book
作者:Wray Zheng
原文:http://www.codebelief.com/article/2017/02/python-advanced-programming-iterator/