python 生成器和迭代器
迭代器协议
1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个Stoplteration异常,以终止迭代(只能往后走不能往前退)
2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)
3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。
迭代:重复做一件事 iterable(可迭代)对象 支持每次返回自己所包含的一个成员的对象
对象实现了__iter__方法
序列类型,如:list,str,tuple
非序列类型,如:dict,file
用户自定义的一些包含了__iter()或__getitem__()方法的类
dir(对象) #查看对象有没有__iter__方法
l1.iter() #当你使用这个方法的时候,就在内存中帮你引用了或者说创建了这个对象的迭代器,我们就可以使用__next()方法
迭代器(iterator)又称游标(cursor),它是程序设计的软件设计模式,是一种可在容器物件(container,如列表等)上实现元素遍历的接口
迭代器是一种特殊的数据结构,在python中,它也是以对象的形式存在的
简单理解方法:对于集体中的每一个元素,想要执行遍历,那么针对这个集体的迭代器定义了遍历集体中每一个元素的顺序或方法
在python中迭代器是遵循迭代协议的对象
使用iter()可从任何序列对象中得到迭代器 若要实现迭代器,需要在类中定义next()方法(python3中是__next__())
要使得迭代器指向下一个元素,则使用成员函数next()
在python,是函数next(),而非成员函数 当没有元素时,则引发StopIteration异常
for循环可用于任何可迭代对象 for循环开始时,会通过迭代协议传递给iter()内置函数,从而能够从可迭代对象中获得一个迭代器,返回的对象含有需要的next方法
#这里显示的是内存对象通过i2.next()调用就好
1 #基于迭代器协议 2 li = [1,2,3] 3 diedai_l = li.__iter__() 4 print(diedai_l.__next__()) 5 print(diedai_l.__next__()) 6 print(diedai_l.__next__()) 7 # print(diedai_l.__next__()) # 超出边界报错 8 9 #下标 10 print(li[0]) 11 print(li[1]) 12 print(li[2]) 13 # print(li[3]) # 超出边境报错 14 15 # 用while循环模拟for循环机制 16 diedai_l = li.__iter__() 17 while True: 18 try: 19 print(diedai_l.__next__()) 20 except StopIteration: 21 print("迭代完毕,循环终止") 22 break 23 24 # for循环访问方式 25 # for循环本质就是遵循迭代器协议的访问方式,先调用diedai_l=li.__iter__方法 26 # 或者直接diedai_l=iter(l),然后依次执行diedai_l.__next__(),直到捕捉到 27 # StopItearation终止循环 28 # for循环所有的对象的本质都是一样的原理
yield作用是创建一个生成器对象,函数中使用yield,会返回一个生成器对象
产生偏移和元素 range可在非完备遍历中用于生成索引偏移,而非偏移处的元素 如果同时需要偏移索引和偏移元素,则可以使用enumerate()函数 此内置函数返回一个生成器对象
>>> url= 'www.baidu.com' >>> enumerate(url) #发现是个内存对象证明这个内置函数是一个生成器对象 <enumerate object at 0x000000000217D3A8> >>> g1 = enumerate(url) >>> g1.next() (0, 'w')
生成器函数:函数体内包含有yield关键字,该函数执行的结果是生成器函数 #生成器本身是迭代器
#yield的功能: 1.与return类似,都可以返回值,但不一样的地方,yield可以返回多次值,而return只能返回一次。
2.为函数封装好了__iter__和__next__方法,把函数的执行结果做成了迭代器
3.遵循迭代器的取值方式obj.next(),触发的是函数的执行,函数暂停与在继续的状态都是由yield保存
如果在函数中调用yield方法会返回一个生成器对象
1 def foo(): 2 print("开始啦") 3 first = yield # return 1 first = None 4 print("第一次",first) 5 yield 2 6 print("第二次") 7 t = test() 8 print(test().__next__()) 9 res = t.__next__() # next(t) 10 print(res) 11 res = t.send("函数停留在first那个位置,我就是给first赋值的") 12 print(res) 13 14 输出结果 15 开始啦 16 None 17 开始啦 18 None 19 第一次 函数停留在first那个位置,我就是给first赋值的 20 2