迭代是访问集合元素的一种方式,迭代器是一个可以记住遍历位置的对象,迭代器对象从集合的第一个元素开始访问,知道所有的元素被访问完结束。迭代器智能往前不会后退
可迭代对象
- 直接作用于for循环的数据类型有以下几种:
- 一类是集合数据类型,如list、tuple、dict、set、str等
- 一类是generator,包括生成器和带yield的generator function
- 这些可以直接作用于for循环的独享统称为可迭代对象:iterable
判断是否可以迭代
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| In [50]: from collections import Iterable
In [51]: isinstance([], Iterable) Out[51]: True
In [52]: isinstance({}, Iterable) Out[52]: True
In [53]: isinstance('abc', Iterable) Out[53]: True
In [54]: isinstance((x for x in range(10)), Iterable) Out[54]: True
In [55]: isinstance(100, Iterable) Out[55]: False
|
而生成器不但可以作用于 for 循环,还可以被 next() 函数不断调用并返回下一个值,直到最后抛出 StopIteration 错误表示无法继续返回下一个值了
迭代器
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
可以使用 isinstance() 判断一个对象是否是 Iterator 对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| In [56]: from collections import Iterator
In [57]: isinstance((x for x in range(10)), Iterator) Out[57]: True
In [58]: isinstance([], Iterator) Out[58]: False
In [59]: isinstance({}, Iterator) Out[59]: False
In [60]: isinstance('abc', Iterator) Out[60]: False
In [61]: isinstance(100, Iterator) Out[61]: False
|
iter()函数
生成器都是 Iterator 对象,但 list 、 dict 、 str 虽然是 Iterable ,却不是 Iterator 。
把 list 、 dict 、 str 等 Iterable 变成 Iterator 可以使用 iter() 函数:
1 2 3 4 5
| In [62]: isinstance(iter([]), Iterator) Out[62]: True
In [63]: isinstance(iter('abc'), Iterator) Out[63]: True
|
总结
1 2 3
| 凡是可作用于 for 循环的对象都是 Iterable 类型 凡是可作用于 next() 函数的对象都是 Iterator 类型 集合数据类型如 list 、 dict 、 str 等是 Iterable 但不是 Iterator ,不过可以通过 iter() 函数获得一个 Iterator 对象
|
如何使用生成器函数实现迭代对象
实际案例
1 2 3 4 5
| 实现一个可迭代对象的类,它能迭代出给定范围内所有素数
pn = PrimeNumbers(1,30) for k in pn: println(k)
|
解决方案
1
| 将该类的__iter__方法实现生成器函数,每次yield返回一个素数
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
class PrimeNumbers(object): def __init__(self, start, end): self.start = start self.end = end
def isPrimeNum(self, k): if k < 2: return False for i in range(2, k): if k % i == 0: return False return True
def __iter__(self): for k in range(self.start, self.end + 1): if self.isPrimeNum(k): yield k
if __name__ == "__main__": for x in PrimeNumbers(1,100): print(x)
|
运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
|