一、定义与作用
1、定义:迭代也是一种循环,但是这种循环每次都是基于上一次的结果而继续,并非单纯重复,迭代器就是执行迭代的工具。
2、作用:迭代器是用来迭代取值,把可迭代对象的值循环取出来。使用迭代器取值,不仅可以用于列表,字符串,元组这些有索引的数据类型,也可以用于字典,集合,文件句柄这种些无索引的数据类型。
二、使用方法
1、可迭代对象:但凡可以用内置的.__iter__()的方法的对象即为可迭代对象。
2、迭代器对象:使用,可迭代对象.__iter__()的方法即可以生成迭代器对象。
3、迭代器取值:使用,迭代器对象.__next__()的方法可以对迭代器对象取值,每调用此方法一次,取出一个可取值,直到所有可取值取完,继续调用的结果会抛出异常StopIteration。
d = {'a': 11, 'b': 2, 'c': 3} d_iter = d.__iter__() # 通过可迭代对象字典 d 生成迭代器 d_iter print(d_iter.__next__()) # 取出迭代器的第一个可取值,结果为 a print(d_iter.__next__()) # 取出迭代器的第二个可取值,结果为 b print(d_iter.__next__()) # 取出迭代器的第三个可取值,结果为 c print(d_iter.__next__()) # 迭代器的可取值已被取完,抛出异常 StopIteration
4、try...except:终止信号。
d = {'a': 11, 'b': 2, 'c': 3} d_iter = d.__iter__() while 1: try: print(d_iter.__next__()) except StopIteration: # 检索异常信号,出现则停止循环 break
5、可迭代对象和迭代器对象的关系:
①可迭代对象:可使用.__iter__()生成迭代器,无法用.__next__()取值。
②迭代器对象:可使用.__iter__()生成迭代器本身,等于没有操作,也可使用.__next__()取值。
③总结:可迭代对象未必是迭代器对象,迭代器对象一定是可迭代对象。
6、文件的特殊性:列表,字符串,元组,字典,集合都只是可迭代对象,而文件句柄是迭代器对象。
7、for循环的工作原理:迭代器循环。
①第一步:对in后面的对象使用.__iter__()生成迭代器对象。
②第二布:对迭代器对象使用.__next__()取一个可取值赋值给for后面的变量名。
③第三步:重复第二步,直到捕捉到StopIteratino信号则结束循环。
④生成某些可迭代对象的功能:如list('abc')的结果是['a'','b','c']。原理同于for循环。
三、迭代器的优缺点
1、优点:
①为有序类型和无序类型的数据提供了统一的迭代取值方式。
②惰性计算:迭代器对象表现的功能相当于一个数据流,可以只是需要时才去使用.__next__()取一个值,迭代器本身在内存中只是一个单纯的功能,占的内存微乎其微,无论数据流多大,对迭代器本身大小并无影响,而列表等类型的数据,因为需要把自身元素都存于内存中,受限于内存的大小,元素的个数是有限的。
2、缺点:
①无法通过获取迭代自身的长度而得知数据流的大小,或者说迭代器自身是没有长度的。
②每次只能取下一个值,不可以返回取值,也就是说同一个迭代器的每个可取值只能被取一次,取完所有可取值迭代器则无法再被取值,若要再取值,需使用.__iter__()重新生成新的迭代器。
四、生成器
1、定义:相比于通过对可迭代对象使用.__iter__()生成的迭代器对象,还可以通过函数内定义yield关键字,再通过调用该函数获得其返回值生成自定义的迭代器,生成器即是此种自定义的迭代器。
2、yield:yield用于返回值,但不同于return,函数一旦遇到return会立即结束执行,而yield会将函数挂起在当前状态,所以当函数体内有yield关键字,可以认为该函数就是用来生成生成器的,此时直接调用函数的话不会产生函数体代码的执行结果,需要把函数调用的结果返回作为生成器使用。
3、使用:通过对生成器使用.__next__()会触发函数体代码的运行,直到遇到一个yield停下来,返回yield后面的值,再次使用.__next__()则在上次的位置向下继续按照此流程执行。
4、用生成器模拟range功能生成的数列迭代器:
def define_range(star, end, step): while star < end: yield star star += step num_iter = define_range(3, 9, 1) for a in num_iter: print(a) # 结果是 3 4 5 6 7 8