迭代器和生成器
一,迭代器
1. 递归和迭代
a、递归的基本概念:程序调用自身的编程技巧称为递归,是函数自己调用自己.一个函数在其定义中直接或间接调用自身的一种方法,
它通常把一个大型的复杂的问题转化为一个与原问题相似的规模较小的问题来解决,可以极大的减少代码量.
递归的能力在于用有限的语句来定义对象的无限集合。
b、迭代:利用变量的原值推算出变量的一个新值.如果递归是自己调用自己的话,迭代就是A不停的调用B。
c、递归中一定有迭代,但是迭代中不一定有递归,大部分可以相互转换.能用迭代的不用递归,递归调用函数,浪费空间,并且递归太深
容易造成堆栈的溢出。
2.迭代器协议
2.1 迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退)
2.2 可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)
2.3 协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。
3. for循环机制
for循环的本质:循环所有对象,全都是使用迭代器协议。
for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器,
然后使用迭代器协议去实现循环访问,这样所有的对象就都可以通过for循环来遍历了,
列表,字符串,元组,字典,集合,文件对象等本质上来说都不是可迭代对象,在使用for循环的时候内部是先调用他们内部的_iter_方法,
使他们变成了可迭代对象,然后在使用可迭代对象的_next_方法依次循环元素,当元素循环完时,会触发StopIteration异常,
for循环会捕捉到这种异常,终止迭代
访问方式常见的有下标方式访问、迭代器协议访问、for循环访问
#1. 下标访问方式 li_test = [1,2,4,677,7] print(li_test[1]) #下标从0开始到n-1
#2. 迭代器协议访问 li_test2=['a','b','c','d'] li=li_test2.__iter__() print(li.__next__()) print(li.__next__()) print(li.__next__()) print(li.__next__()) print(li.__next__()) #StopIteration,超出边界会报错
#3 for循环机制访问 li_test3=[1,2,3,4] #for循环本质:先调用li = li_test3.__next__()生成可迭代对象,然后是哟个li.__next()__依次循环元素。 for i in li_test3: print(i) #使用while模仿for循环 li=li_test3.__iter__() 3 while True: 4 try: 5 print(li.__next__()) 6 except StopIteration: 7 print('迭代完毕了,循环终止了') 8 break
二,生成器
生成器类似于一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己内置的__iter__方法),所以生成器就是可迭代对象
生成器分类及在python中的表现形式:(Python有两种不同的方式提供生成器)
1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,
以便下次重它离开的地方继续执行
2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表,按需取出对象
为何使用生成器之生成器的优点
Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果,提高了取数据的效率,优化了内存空间的使用。