# 迭代器 # 迭代器是一个重复的过程,每次取值都是基于上一次的结果,而进行迭代取值的工具 # # 拥有: # __iterator__ 和 __next__内置方法 # 注意: # 1.重复取值,单纯的重复取值的不是迭代器对象 # 2.每次取值都是基于上次取值结果而进行 # # 作用: # 提供了一种不依赖于索引的迭代取值的方式 # # 分类: # 可迭代的对象:list tuple dict set # 迭代器对象:file 生成器 内置有iter next方法 # 实例: # l=[1,2,3,4,5,6] # iter_l=l.__iter__()#调用可迭代的对象__iter__得到一个新的迭代器对象 # print(iter_l.__next__())#迭代1次 # print(iter_l.__next__())#迭代2次 # print(iter_l.__next__())#迭代3次 # 按照next的次数依次的输出结果,有几个next就输出几次结果 #是依据上次的迭代结果一次进行next结果输出 #因为只产生了依次iter_l=l.__iter__(),下面的next的输出都是按照这个迭代对象 # 依次的输出 # 错误方式: # print(l.__iter__().__next__())#迭代1次 # print(l.__iter__().__next__())#迭代2次 # print(l.__iter__().__next__())#迭代3次 # 输出结果: # 1 # 1 # 1 # 因为进行迭代时,每次都是l列表产生新的迭代器的对象,都是重新进行next,是一个单纯的重复的过程 # 注:之所以可迭代对象和迭代器对象都有iter,和next的方法,是为了进行统一,迭代机制统一。 # # 总结: # 优点: # 1.提供一种不依赖索引的取值方式 # 2.同一时刻内存中只存在一个值,而且只能往后去 # 缺点: # 1.取值不能按照索引取值,只能往后一个个的取 # 2.无法预测迭代器的长度,因为迭代器是一个个的网下取值,知道报错,才停止。
迭代器
迭代是一个重复的过程,并且每次重复都是基于上一次的结果而来 #仅仅循环,不是迭代 可迭代对象:在python中,但凡内置有__iter__方法的对象,都是可迭代的对象 以下都是可迭代的对象 str1='hello' list1=[1,2,3] tup1=(1,2,3) dic={'x':1} s1={'a','b','c'} f=open('a.txt','w',encoding='utf-8') 迭代器:迭代取值工具,可迭代的对象执行__iter__方法得到的返回值就是迭代器对象 dic={'x':1,'y':2,'z':3} iter_dic=dic.__iter__() print(iter_dic.__next__()) print(iter_dic.__next__()) print(iter_dic.__next__()) print(iter_dic.__next__()) 可迭代的对象vs迭代器对象 可迭代的对象:str,list,tuple,dict,set,file(文件本身就是迭代器) a、获取可迭代对象的方式:无须获取,python内置str,list,tuple,dict,set,file都是可迭代对象 b、特点: 内置有__iter__方法的都叫可迭代的对象,执行该方法会拿到一个迭代器对象 迭代器对象:文件对象本身就是迭代器对象 #迭代器对象一定是可迭代对象 a、获取迭代器对象的方式: 执行可迭代对象的__iter__方法,拿到的返回值就是迭代器对象 b、特点: 内置有__next__方法,执行该方法会拿到迭代器对象中的一个值 内置有__iter__方法,执行该方法会拿到迭代器本身 iter_x=x.__iter__() iter_x.__next__() print(iter_x.__iter__().__iter__().__iter__().__iter__() is iter_x) #拿到的还是本身 迭代器的优缺点分析 迭代器提供了一种可不依赖于索引的取值方式(优点) #字典无序,没有办法通过索引取值,可通过迭代器取值 l=open('a.txt','r',encoding='utf-8') iter_l=l.__iter__() while True: try: print(iter_l.__next__()) except StopIteration: break 迭代器更加节省内存(优点)#迭代器本身是一个内存地址 #range在python2中是一个列表,在python3中是一个迭代器 取值麻烦,只能一个一个取,只能往后取(缺点) 并且是一次性的,无法用len获取长度(缺点) for循环原理分析 a、for 循环称之为迭代器循环,in后跟的必须是可迭代的对象 #while 循环称为条件循环 b、for循环会执行in后对象的__iter__方法,拿到迭代器对象 c、然后调用迭代器对象的__next__方法,拿到一个返回值赋值给line,执行一次循环体 d、周而复始,直到取值完毕,for循环会检测到异常自动结束循环 for line in l: #iter_l=l.__iter__() print(line) for item in {'x':1,'y':2}: print(item) 生成器:函数内包含有yield关键字,再调用函数,就不会执行函数体代码,拿到的返回值就是一个生成器对象 def chicken(): print('=====>first') yield 1 print('=====>sencond') yield 2 print('=====>third') yield 3 obj=chicken() res=obj.__next__() print(res) res1=obj.__next__() print(res1) res2=obj.__next__() print(res2) 1、iter_obj=obj.__iter__(),拿到迭代器 2、触发iter_obj.__next__(),拿到该方法的返回值,赋值给item 3、周而复始,直到函数内不在有yield,即取值完毕 4、for会检测到StopIteration异常,结束循环 for item in obj: print(item) 总结yield: 1、为我们提供了一种自定义迭代器的方式,可以在函数内用yield关键字,调用函数拿到的结果就是一个生成器,生成器就是迭代器 2、yield可以像return一样用于返回值,区别是return只能返回一次值,而yield可返回多次。因为yield可以保存函数执行的状态 def my_range(): print('start........') n=0 while True: yield n n+=1 obj=my_range() print(obj) print(obj.__next__()) print(obj.__next__()) print(obj.__next__()) print(obj.__next__()) for i in my_range(): print(i) def my_range(start,stop,step=1): n=start while n < stop: yield n #yield 4 n+=step #5 obj=my_range(3,7,2) #3,5, print(obj.__next__()) print(obj.__next__()) print(obj.__next__()) print(obj.__next__()) print(obj.__next__()) for item in my_range(5,10,2): print(item) 生成器之yield的表达式形式 def eat(name): print('%s ready to eat' %name) food_list=[] while True: food=yield food_list # food='骨头' food_list.append(food) #food_list=['泔水','骨头'] print('%s start to eat %s' %(name,food)) dog1=eat('alex') 1、必须初始化一次,让函数停在yield的位置 res0=dog1.__next__() print(res0) 2、接下来的事,就是喂狗 send有两方面的功能 a、给yield传值 b、同__next__的功能 res1=dog1.send('泔水') print(res1) res2=dog1.send('骨头') print(res2) res3=dog1.send('shit') print(res3)