本文主要介绍Python迭代器的相关知识。
在此之前,先用一幅图,了解下容器(container)、可迭代对象(iterable)、迭代器(iterator)、生成器(generator)、列表/集合/字典推导式(list,set,dict comprehension)等概念的一些关系(本图片来源于互联网,由于画的很好,这里借鉴过来)。
容器(container)
容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in
,not in
关键字判断元素是否包含在容器中。通常这类数据结构把所有的元素存储在内存中(也有一些特例,并不是所有的元素都放在内存,比如迭代器和生成器对象)在Python中,常见的容器对象有:1
2
3
4
5list, deque, ....
set, frozensets, ....
dict, defaultdict, OrderedDict, Counter, ....
tuple, namedtuple, ....
str
容器比较容易理解,因为你就可以把它看作是一个盒子、一栋房子、一个柜子,里面可以塞任何东西。从技术角度来说,当它可以用来询问某个元素是否包含在其中时,那么这个对象就可以认为是一个容器。
可迭代对象(iterable)
可直接作用域for循环的类型,主要包括以下几类:
1.集合数据类型,如 list 、 tuple 、 dict 、 set 、 str 等;
2.generator ,包括生成器和带 yield 的generator function。
这些可以直接作用于 for 循环的对象统称为可迭代对象: Iterable 。
判断是否可以迭代
可以使用 isinstance() 判断一个对象是否是 Iterable 对象:1
2
3
4
5
6from collections import Iterable
isinstance([], Iterable) # True
isinstance({}, Iterable) # True
isinstance('abc', Iterable) # True
isinstance((x for x in range(10)), Iterable) # True
isinstance(100, Iterable) # False
而生成器不但可以作用于 for 循环,还可以被 next() 函数不断调用并返回下一个值,直到最后抛出 StopIteration 错误表示无法继续返回下一个值了。
迭代器(Iterator)
它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值。如果容器中没有更多元素了,则抛出StopIteration异常。
所以,迭代器就是实现了工厂模式的对象,它在你每次你询问要下一个值的时候给你返回。
比如itertools函数返回的都是迭代器对象。
生成无限序列:1
2
3
4
5
6from itertools import count
13) counter = count(start=
next(counter)
13
next(counter)
14
从一个有限序列中生成无限序列:1
2
3
4
5
6
7
8
9
10from itertools import cycle
'red', 'white', 'blue']) colors = cycle([
next(colors)
'red'
next(colors)
'white'
next(colors)
'blue'
next(colors)
'red'
从无限的序列中生成有限序列:1
2
3
4
5
6
7
8
9from itertools import islice
'red', 'white', 'blue']) # infinite colors = cycle([
0, 4) # finite limited = islice(colors,
for x in limited:
print(x)
red
white
blue
red
为了更直观地感受迭代器内部的执行过程,我们自定义一个迭代器,以斐波那契数列为例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Fib:
def __init__(self):
self.prev = 0
self.curr = 1
def __iter__(self):
return self
def __next__(self):
value = self.curr
self.curr += self.prev
self.prev = value
return value
f = Fib()
0, 10)) list(islice(f,
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
实例变量prev和curr用户维护迭代器内部的状态。每次调用next()方法的时候做两件事:
1.为下一次调用next()方法修改状态
2.为当前这次调用生成返回结果
迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。
判断Iterator对象
可以使用 isinstance()判断一个对象是否是Iterator对象:1
2
3
4
5
6from collections import Iterator
isinstance((x for x in range(10)), Iterator) # True
isinstance([], Iterator) # False
isinstance({}, Iterator) # False
isinstance('abc', Iterator) # False
isinstance(100, Iterator) # False
iter()函数
生成器都是Iterator对象,但 list、dict、str 虽然是 Iterable,却不是Iterator。
把 list、dict 、str等Iterable变成Iterator可以使用iter() 函数:1
2isinstance(iter([]), Iterator) # True
isinstance(iter('abc'), Iterator) # True
参考资料: