⾸先我们要理解迭代器(iterators)。 迭代器是可以遍历⼀个容器(特别是列表) 的对象。 然⽽, ⼀个迭代器在遍历并读取⼀个容器的数据元素时, 并不会执⾏⼀个迭代。 你可能有点晕了, 那我们来个慢动作。 换句话说这⾥有三个部分:
上⾯这些部分互相联系。 我们会先各个击破来讨论他们, 然后再讨论⽣成器(generators)。
Python中任意的对象, 只要它定义了可以返回⼀个迭代器的__iter__⽅法, 或者定义了可以⽀持下标索引的__getitem__⽅法(这些双下划线⽅法会在其他章节中全⾯解释),那么它就是⼀个可迭代对象。 简单说, 可迭代对象就是能提供迭代器的任意对象。
任意对象, 只要定义了next(Python2) 或者__next__⽅法, 它就是⼀个迭代器。 就这么简单。
⽤简单的话讲, 它就是从某个地⽅(⽐如⼀个列表) 取出⼀个元素的过程。 当我们使⽤⼀个循环来遍历某个东西时, 这个过程本⾝就叫迭代。
⽣成器也是⼀种迭代器, 但是你只能对其迭代⼀次。 这是因为它们并没有把所有的值存在内存中, ⽽是在运⾏时⽣成值。 你通过遍历来使⽤它们, 要么⽤⼀个“for”循环, 要么将它们传递给任意可以进⾏迭代的函数和结构。 ⼤多数时候⽣成器是以函数来实现的。 然⽽,它们并不返回⼀个值, ⽽是yield(暂且译作“⽣出”)⼀个值。
#!coding:utf8
def num_generators():
for i in range(0,3):
yield i
if __name__=='__main__':
for num in num_generators():
print num
输出结果是
0
1
2
#!coding:utf8
def num_generators():
for i in range(0,3):
yield i
if __name__=='__main__':
nums = num_generators()
print next(nums), next(nums), next(nums)
print next(nums)
结果如下:
0 1 2
File “E:/pycharmworkspace/deep/csdn/csdn.py”, line 10, in
print next(nums)
StopIteration
我们可以看到, 在yield掉所有的值后, next()触发了⼀个StopIteration的异常。这个异常告诉我们所有的值都已经被yield完了。联想一下为什么使用for循环就没有就没这异常呢,原因很简单:for循环会自动捕捉到这个异常并停⽌调⽤next()
#!coding:utf8
if __name__=='__main__':
csdn="CSDN"
print next(csdn)
运行结果如下
Traceback (most recent call last):
File “E:/pycharmworkspace/deep/csdn/csdn.py”, line 6, in
print next(csdn)
TypeError: str object is not an iterator
由上面的结果可以知道字符串(str)不是一个迭代器,但是我们却是可以用for循环遍历字符串,说明字符串是一个可迭代对象
那么我们如何将一个可迭代对象变成一个迭代器呢?这里我需要引入一个python内置函数iter(),代码如下:
#!coding:utf8
if __name__=='__main__':
csdn=iter("CSDN")
print next(csdn),next(csdn),next(csdn),next(csdn)
运行结果如下:
C S D N