最近在读《流畅的python》,对生成器有了进一步的认识。理解生成器前,要理解可迭代对象(iterable)和迭代器(iterator)。
- 按照书中的说法,凡是能应用iter()函数的对象,都是可迭代对象
- 可迭代对象必须实现__iter__方法
- 凡是能应用next()函数的对象,都是迭代器
- 迭代器必须实现__next__和__iter__方法
- 不断地对迭代器应用next()能获取到迭代器的每一个元素,直到抛出StopIteration异常,以后再对它应用next()就一直抛出StopIteration异常,也就是说迭代器只能被next()遍历一遍
- 可迭代对象不等于迭代器,对可迭代对象应用iter()可以得到迭代器
- 对迭代器应用iter()得到的还是是它自己
下面看例子
>>> l = list(range(3))
>>> l
[0, 1, 2]
>>> next(l)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list object is not an iterator
>>> li = iter(l)
>>> li
<listiterator object at 0x022C3570>
>>> next(li)
0
>>> next(li)
1
>>> next(li)
2
>>> next(li)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> next(li)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
首先我们得到一个list对象,对它应用next()函数,报错list不是迭代器。对,list是可迭代对象,可以对它应用iter()函数,得到一个迭代器对象li。
不断的对li应用next()函数,得到每一个元素,然后抛出了StopIteration异常,再应用next()函数还是这个异常。
>>> iter(li)
<listiterator object at 0x022C3570>
对li应用iter()得到的还是它自己,注意内存地址都是0x022C3570。
在python语言里,迭代器用于支持:
- for循环
- 构建和扩展集合类型
- 逐行遍历文本文件
- 列表推倒、字典推导和集合推导
- 元组拆包
- 调用函数时,使用*拆包实参
上面铺垫了这么多,都是为了引出下面这一句,直接摘录书中原话了:
"在python社区中,大多数时候都把迭代器和生成器视作同一概念。"
记住了,生成器就是迭代器。