python中经常用到迭代,但是对于迭代器、生成器一直处于模糊的理解,查看了不少资料,感觉有些清晰了。
什么是迭代
通过for循环不断的拿到list中的值就是迭代,迭代就是循环做重复的事情。
for i in range(10): print(i)
可以通过for循环进行迭代的对象称为可迭代对象(Iterable),如何判断是否是可迭代对象,可以用collection模块中的Iterable来判断
>>> from collections import Iterable >>> isinstance([],Iterable) True >>> isinstance("",Iterable) True >>> isinstance({},Iterable) True >>> isinstance(123,Iterable) False >>> isinstance((),Iterable) True
可迭代对象内部都实现了_iter_方法,例如list,通过help(list)查看
| __iter__(self, /) | Implement iter(self).
可迭代对象可以通过循环拿到值,但是可迭代对象不是迭代器。
迭代器
为什么list、dict、str等数据类型不是Iterator?这是因为Python的迭代器(Iterator)对象表示的是一个数据流,迭代器(Iterator)对象可以被next() 函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
迭代器(Iterator)甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
迭代器可以通过next函数不断计算下一个数据。
>>> c=iter(b) >>> c >>> next(b) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'list' object is not an iterator >>> next(c) 0
可以看到list是可迭代对象,但是无法使用next函数,因为它不是迭代器,而c则可以
创建迭代器的方法
可以通过 iter(list/set..) 来把一个可迭代对象创建为迭代器。
生成器
生成器可以理解为特殊的迭代器,它也实现了iter和next方法,也是基于计算的迭代,一边计算一边迭代的机制称为generator
创建生成器的方法
1. 通过列表推导式,把列表生成式的[]改为()
>>> g=(x for x in range(10)) >>> type(g) <class 'generator'>
2.通过生成器函数得到一个生成器,定义一个包含yield的函数,普通函数中通过return返回值,返回后整个函数已经结束,而生成器函数中通过yield返回值,返回后会记录yield的位置,然后下次再调用会从yield的位置继续执行
def func(n): a=1 for i in range(n): yield a a+=i a=func(5) print(a) print(a.__next__()) print(a.__next__()) print(a.__next__()) print(a.__next__()) print(a.__next__()) print(a.__next__()) print(a.__next__()) print(a.__next__())
看下结果,返回的是一个生成器,可以通过next函数不断拿到值,直到抛出StopIteration
总结:
1. 可迭代对象不一定是迭代器
2.迭代器一定是可迭代对象
3.实现了__next__函数(或可以通过next函数取值),__iter__函数的是迭代器
4.生成器是特殊的迭代器,可以通过列表推导式或者函数中使用yield来获得生成器