前一段时间和同事聊到Python技术知识,发现自己对生成器,迭代器傻傻分不清楚,于是乎查文档,找资料,有了此文。
通过本文大家可以了解到迭代器,生成器,生成器表达式,容器的定义以及关系。
关系图(http://nvie.com/posts/iterators-vs-generators/)
先对上面的关系进行解释说明
生成器包括生成器表达(generator expression)和生成器函数(generator function)。 生成器(generator)是迭代器(iterator),但是反过来不一定成立,同时生成器也是可迭代的。 迭代器(iterator)都是可迭代的(iterable),并且实现了next()/__next()__方法。 元组,列表,集合构成容器这些对象都是可迭代的。
接下来我们深入浅出的去了解迭代器,生成器是什么,如何使用。
相信大家都知道迭代的含义,就是可以循环遍历。 那什么是可迭代对象?通俗的将就是可以使用for x in iterable_obj 或者while 循环遍历的对象,比如list,set,tuple,dict等对象。我们可以通过isinstance()方法来判断,参考例子:
In [30]: from collections import Iterable
In [31]: isinstance('python', Iterable)
Out[31]: True
In [32]: s=3 # s为数字,不可迭代
In [33]: isinstance(s, Iterable)
Out[33]: False
In [35]: l = [1,2,3,4] #列表可用for循环遍历,可迭代
In [35]: isinstance(l, Iterable)
Out[35]: True
In [37]: w=(1,2,3) #元组可用for循环遍历,可迭代
In [38]: isinstance(w, Iterable)
Out[38]: True
从上面的检测来看 s=3 ,s是一个数值,不可迭代。其他的对象都是可以被循环访问的,即可迭代。
迭代器是可以被next()函数调用并返回下一个值的对象,即Iterator。一个对象可迭代,是否就说明它是迭代器呢?我们继续使用isinstance 检测
In [37]: s=[1,2,3] #列表可以用for循环遍历,可迭代
In [39]: from collections import Iterable,Iterator
In [40]: isinstance(s, Iterator)
Out[40]: False ##
从结果来看s是一个列表,可迭代的对象(iterable)不一定是迭代器(iterator)。为什么列表,集合,字典等对象是可迭代但是不是迭代器呢?
Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。 我们可以把iterator当做有序序列,但我们不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,只有在需要返回下一个数据时它才会计算,即(lazy evaluation)。构造有几百万个值的列表所占用的内存大于几十M,而迭代器对象占用几十个字节的空间。
如何构造迭代器呢?本文介绍两种方式:
生成器是迭代器的一种,不过生成器不需要实现__iter__()和__next__(),只要使用yield关键字返回值。当一个生成器函数调用yield,生成器函数的"状态"会被冻结,所有的变量的值会被保留下来,下一行要执行的代码的位置也会被记录,直到再次调用next()。一旦next()再次被调用,生成器函数会从它上次离开的地方开始。如果永远不调用next(),yield保存的状态就被无视了。从下面的例子可以出来yield运行机制:
In [79]: def gen():
...: yield 1
...: yield 2
...: yield 3
...:
In [80]: g=gen()
In [81]: next(g)
Out[81]: 1
In [82]: next(g)
Out[82]: 2
In [83]: next(g)
Out[83]: 3
In [84]: next(g)
----------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-85-5f315c5de15b> in <module>()
----> 1 next(g)
StopIteration:
在python中生成器有两种:
https://www.cnblogs.com/wj-1314/p/8490822.html
http://python.jobbole.com/87613/
http://python.jobbole.com/84527/
http://python.jobbole.com/87805/
http://python.jobbole.com/87312/
https://www.zhihu.com/question/20829330
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014317799226173f45ce40636141b6abc8424e12b5fb27000
https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386832360548a6491f20c62d427287739fcfa5d5be1f000