生成器:
可以理解为一种数据类型,可自动实现迭代器协议,可以理解为生成器就是可迭代对象(其他数据类型可调用内置地__iter__(),如果没有内置的__iter__(),即不可迭代)
状态挂起:使用yield语句返回一个值。使该函数挂起该生成器函数的状态,保留信息,以便之后从它离开的地方继续执行
优点:延迟计算 一次返回一个结果 ,等待下次需要再继续返回结果(处理较大的数据可以使用 )
迭代器:
迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项 要么引起一个StopIteration异常,以终止迭代(只能往后走 不能往前退)
可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter()__方法
协议:协议是一种约定,可迭代对象实现了迭代器协议(for sum min max 使用迭代器协议访问对象)
1.生成器函数:
使用yield函数并非return语句
def test() yield 1 #可多个返回值 return只能一个 yield 2 yeild 3 print(test())
g=test()#g:生成器 自动实现迭代器协议
print(g.__next__())
1 # iter_l =x.__iter__()#遵循迭代器协议,生成可迭代对象 2 # print(iter_l.__next__())#for循环和索引没关系 基于迭代器机制 3 # python 中for循环的强大之处在于可以遍历序列和非序列类型 例如文件 4 f = open('字节方式与文件','r+',encoding='utf-8') 5 text_f =f.__iter__() 6 print(text_f.__next__(),end='') 7 print(text_f.__next__()) 8 print(text_f.__next__())
补充知识:三元表达式:
name='guoguo'
'TT' if name=='guoguo' else 'FF'【三元表达式】【如果name=guoguo 则返回TT 否则返回FF】
赋值给result得到结果
result=‘TT’ if name=='guoguo' else 'FF'
print(result)
补充知识:列表解析:(缺点:生成列表 放入内存中 若该列表过大则占用内存较大)
缺点:占用内存大、效率低
1 egg_list = [] 2 for i in range(10): 3 egg_list.append('鸡蛋%s',%i) 4 print(egg_list) 5 6 列表解析: 7 l = ['鸡蛋%s' %i for i in range(10)]
l = ['鸡蛋%s' %i for i in range(10) if i>5]#三元表达式:'鸡蛋%s' %i for i in range(10) if i>5
l = ['鸡蛋%s' %i for i in range(10) if i>5 else ]#错误 没有四元表达式 8 print(l)
生成器表达式:
1 laomuji=('鸡蛋%s' %i for i in range(10))#生成器表达式(直接实现迭代器协议) 2 print(laomuji)#生成器 3 print(laomuji.__next__())#运行结果:鸡蛋0 4 print(laomuji.__next__())#运行结果:鸡蛋1 5 print(laomuji.__next__())#运行结果:鸡蛋2 6 print(laomuji.__next__())#运行结果:鸡蛋3 7 print(next(laomuji))# 生成器只能遍历一次。否则报错。运行结果:鸡蛋4【小于等于鸡蛋9 大于则报错 有界限 大于则StopIteration】
总结:
1.把列表解析的[]换成()则为生成器表达式
2.列表解析与生成器表达式都为便利的编程方式,但是生成器相对更节省内存【一个一个取值 next()】
3.python使用迭代器协议 使for循环更通畅,而且大部分内置函数也使用迭代器协议 map() sum() max() min() reduce() filter()