一、迭代器
-
迭代
: 访问集合元素的一种方式; 比如for循环,逐个获取数据的过程叫做迭代 -
迭代器对象
:内置__iter__() 、next() 方法对象 -
迭代器:支持next操作对象,当执行next操作,返回其中的一个元素
当所有的的元素都被返回后,再执行next报职场 StopIteration迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。
迭代器只能往前不会后退可迭代对象的本质 即迭代器帮助我们对其进行迭代遍历使用。
可迭代对象通过__iter__方法向我们提供一个迭代器,在迭代一个可迭代对象的时候,实际上就是先获取该对象提供的一个迭代器,然后通过这个迭代器来依次获取对象中的每一个数据. -
迭代器的应用场景
迭代器最核心的功能是通过next()函数的调用来返回下一个数据值返回的数据不是在已有的数据集合中读取得到的,而是通过程序按照一定定规律计算生成的,可以不依赖已有的数据集合,不用将所有要迭代数据一次性缓存供后续读取,节省大量内存空间.
二、生成器
生成器本质就是一个带yield的函数,它记住上一次返回时函数体中的位置。
生成器不仅记住了他的数据状态,还记住了程序执行的位置
因为yield会挂起这个函数,直到send调用的时候,函数又重新恢复到原来的状态,完成后续的赋值工作
生成器一定是可迭代的,也一定是迭代器对象
生成器:一边循环一遍计算,返回一个结果;不会一次生成所有的结果,对大数据量处理非常有用;
优点:数据量很大时,会按需产生数据,不会占用大量内存
迭代器:
如果一个对象可以被遍历,那么这个对象一定是可迭代对象,可迭代对象一定是含有iter方法的,
但是这个对象不一定是迭代器,迭代器还需要有next方法。
iter方法实际上是拿到可迭代数据,然后交给next方法进行迭代。
综上,一个迭代器一定是可迭代对象,迭代器(iterator)必须实现iter方法和next方法。
生成器:
生成器实际上就是一个迭代器,生成器中,iter方法不需要写,因为在生成器中已经自动帮我们实现了。
生成器中的yield方法实际上就是迭代器中next中的return,区别在于,return是返回数据后,相关环境会被回收,
而yield则是在返回数据后,保留环境,停在当前步骤,再次使用时,直接从上次结果继续进行。
迭代器对象:可以转化为迭代器的对象(只要内置__iter__() 、__next__() 方法)
迭代器对象调用__next__() 方法,会得到迭代器的下一个值
迭代器对象调用__iter__() 方法,会得到迭代器本身(和没调一样)
列表、字典、元祖、集合、文件等
li = [1, 4, 5, 2]
for x in li:
print(x)
s = 'zxcvb'
for x in s:
print(x)
如何对一个迭代器做切片操作
使用标准库下的itertools.islice,
它能返回一个迭代对象切片的生成器
from itertools import islice
for line in islice(f, 3, 6): # 前500参数1, 后500, None
print(line)
l = range(20)
t = iter(l)
for x in islice(t, 5, 10):
print(x)# 会消耗原来的迭代对象
print('====================')
for x in t:
print(x)#
三、斐波那契数列迭代器
0 1 1 2 3 5 8 13 21 34 55 89…前两项0 1 , 后一项是前两项的和
class Fib(object):
def__init__(self, n):
self.n = n #记录位置信息
self.index =0 #保存当前数列第几个数字
self.num1 =0 #初始值为0
self.num2 =2 #第二个数字
# __iter__方法要返回一个迭代器,迭代器自身也是是一个迭代器,所以迭代器的__iter__方法返回自身即可。
def__iter__(self):#一个具备了__iter__方法的对象,就是一个可迭代对象
returnself #一个实现了__iter__方法和__next__方法的对象,就是迭代器
def__next__(self):# 使用next()函数调用的是迭代器对象的__next__方法
ifself.index <self.n:
num = self.num1
self.num1,self.num2 =self.num2,self.num1+self.num2
self.index +=1 #当前数字下标
return num
else:
raiseStopIteration #注意,当已经迭代完最后一个数据后,再次调用next()函数会抛出StopIteration的异常
if __name__ =='__main__':
fori inFib(100):
print(i)
li =list(Fib(15)) # list、tuple是可迭代对象,可以通过iter()函数获取这些可迭代对象的迭代器
print(li) # 然后可以对获取到的迭代器不断使用next()函数来获取下一条数据
tp = tuple(Fib(15))
print(tp)