四. python进阶(生成器,生成函数 )
"""def ret(): return 111 print(ret()) # 111 """ """ def ret(): yield 111 print(ret()) # <generator object ret at 0x000001A5A195FF68> 返回一个生成器 """ """def ret(): yield 111 print(222) aa=ret() # 不会执行你的函数 拿到的生成器 bb=aa.__next__() # 会执行到一个yield print(bb) cc=aa.__next__() print(cc) # StopIteration """ # 函数中有yiled 这就是一个生成器函数 获取的是生成器 这个时候不执行函数 一个惰性机制 # yield 相当于 return 可以返回数据 但是yiled 不会彻底中断函数 分段执行函数 # gen.__next__()执行函数 执行下一个yiled # gen.__next__() 继续执行下一个yield # 一个惰性机制 只能向下走 省内存 """ def coder(): for i in range(55): yield "衣服"+str(i) gen=coder() # 获取到生成器 # aa=gen.__next__() # print(aa) # bb=gen.__next__() # print(bb) cc=0 for i in gen: cc+=1 if cc>6: break print(i) """ # send # send()和 __next__()是一样 可以执行yiled 可以给上一个yiled传值 def func(): print("111111") yield 1 print("222222") yield 2 print("333333") yield 3 print("444444") # yield 0 最后收尾一定是yiled 不然会报错 # StopIteration g=func() print(g.__next__()) print(g.__next__()) print(g.__next__()) # print(g.__next__()) # StopIteration print("**************************************send************************************") print("**************************************************************************") """def func(): print("111111") a=yield 1 print(a) print("222222") b=yield 2 print(b) print("333333") c=yield 3 print(c) print("444444") d=yield 66666 g=func() print(g.__next__()) print(g.__next__()) print(g.__next__()) print(g.__next__()) # # 111111 # 1 # None # 222222 # 2 # None # 333333 # 3 # None # 444444 # 66666 """ def func(): print("111111") a=yield 1 print(a) print("222222") b=yield 2 print(b) print("333333") c=yield 3 print(c) print("444444") yield 999999999999 # 注意最后一个 yiled 是不能传值的 不然会报错 g=func() print(g.__next__()) # 第一次必须是__next__() 就是开头必须是__next__() print(g.send("哈哈哈哈哈")) print(g.send("啦啦啦啦啦")) print(g.send("叽叽叽叽")) # # 111111 # 1 # 哈哈哈哈哈 # 222222 # 2 # 啦啦啦啦啦 # 333333 # 3 # 叽叽叽叽 # 444444 # 999999999999
一 .生成器
理解生成器 函数
只有含有yield的关键字都是生成器函数 但是不能和return共用 注意 yield只能在函数内部使用
生成器 本质就是迭代器
用到 处理很多数据时应用 yield 一条一条的返回数据
def aa(): print(1) yield "a" # 生成器函数:执行之后会得到一个生成器作为返回值 cc=aa() print(cc) # <generator object aa at 0x00000259830C2EB8> 生成器 print(cc.__next__()) # 1 a
def aa(): print(1) yield "a" print(2) yield "b" yield "c" cc=aa() g=cc.__next__() print(g) # 1 a g=cc.__next__() print(g) # 2 b g=cc.__next__() print(g) # c
def aa(): print(1) yield "a" print(2) yield "b" yield "c" c=aa() for i in c: print(i)
def dd(): for i in range(5): yield "生成50个哇哈哈%s"%i a=dd() for i in a: print(i) print("*************************************") def dd(): for i in range(21): yield "生成50个哇哈哈%s"%i a=dd() dd=0 for i in a: dd+=1 print(i) if dd>6: break print("*************************************") # 表示生成了两个迭代器 而生成器函数可以作用于一个迭代器 ll=[1,2,3,4,5,6] for i in ll: if i==3: break print(i) print("*************************************") for i in ll: print(i)
def ff(): for i in range(100): yield "生成%s"%i f=ff() f1=ff() print(f.__next__()) print(f.__next__()) print(f.__next__()) print(f.__next__()) print(f.__next__()) print("***********") print(f1.__next__()) print(f1.__next__()) # 说明了自己走自己的 相当于两个迭代器 # 生成0 # 生成1 # 生成2 # 生成3 # 生成4 # *********** # 生成0 # 生成1
def aa(): print(1) yield "a" dd=aa() # print(list(dd)) 数据类型强制转换 也可以取值 但是太占内存了 print(dd) # 生成器函数 :执行之后会得到一个生成器作为返回值 # generator 生成器 print(dd.__next__()) # <generator object aa at 0x000001CF75392EB8> # 1 # a
def bb(): print("aaaaa") yield "我是aaaa" print("bbbbb") yield "我是bbbb" yield "我是ccc" print(bb()) cc=bb() print(cc) print(cc.__next__()) # aaaaa # 我是aaaa print(cc.__next__()) # bbbbb # 我是bbbb
def bb(): print("aaaaa") yield "我是aaaa" print("bbbbb") yield "我是bbbb" yield "我是ccc" cc=bb() # print(cc.__next__()) # aaaaa 我是aaaa # print(cc.__next__()) # bbbbb 我是bbbb # print(cc.__next__()) # 我是ccc print("**************************************") print(cc,"这是迭代器哈哈哈哈哈") for i in cc: print(i,"for循环") # aaaaa # 我是aaaa for循环 # bbbbb # 我是bbbb for循环 # 我是ccc for循环
# 边生成数据边处理数据 def ff(): for i in range(100): yield "生成%s"%i f=ff() for i in f: print(i) # 边生成数据边处理数据 def ff(): for i in range(100): yield "生成%s"%i f=ff() cont=0 for i in f: cont+=1 if cont>50: break print(i)
def aa(): print(111) yield "我是111" print(222) yield "我是222" yield "我是垃圾" b=aa() # print(b) print(b.__next__()) # 111 我是111 print(b.__next__()) # 222 我是222 print(b.__next__()) # 我是垃圾
1. send方法() 以在获取下一个值时 可以给上一个yield的位置传递参数
def aa(): print(111) yield "我是111" print(222) yield "我是222" yield "我是垃圾" b=aa() # print(b) print(b.__next__()) # 111 我是111 print(b.send(None)) # send的效果和next一样 # 222 我是222
# send获取下一个值的效果和next一样的 # 但是send 可以在获取下一个值时 可以给上一个yield的位置传递参数 # send 注意使用 # 第一次使用生成器的时候 是必须用next获取下一个值 # 最后一个yield不能接受外部的值 def aa(): print(111) cont=yield "我是111" print("我是",cont) print(22222) yield "我是333333" b=aa() # print(b) print(b.__next__()) # 111 # 我是111 print(b.send("hello")) # send的效果和next一样 但是可以传参数 # 我是 hello # 22222 # 我是333333
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 获取移动平均值 # 10 20 30 10 # # avg=sum/count def bb(): sum=0 count=0 avg=0 while True: num=yield avg sum+=num count+=1 avg=sum/count c=bb() c.__next__() av=c.send(20) av=c.send(30) av=c.send(10) print(av)
2. yield from
def gen(): a='123456' b='abcdef' yield from a yield from b a=gen() for i in a: print(i)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 监听文件用户文件输入 aa=r"D:\aaaa育\01day\生成器函数\aa.txt" # strip() 方法用于移除字符串头尾指定的字符 def cc(bb): with open(bb,encoding="utf-8")as f1: while True: li=f1.readline() if li.strip(): #去掉回车空格 yield li.strip() dd=cc(aa) for i in dd: print("****",i)
def bb(): for i in range(20): yield "生成%d"%i aa=bb() cc=0 for i in aa: cc+=1 if cc>6: break print(i) # 生成0 # 生成1 # 生成2 # 生成3 # 生成4 # 生成5
# with open('25生成器人口普查','r',encoding='utf-8') as f: # 利用生成器取人口数 def g(): with open('./25生成器人口普查.py','r',encoding='utf-8') as f: for i in f: yield i a=g() c1=a.__next__() c2=a.__next__() print(c1) print(c2) # {"name":"上海","renkou":7700} # {"name":"湖北","renkou":1400} print("*******************# 利用生成器取人口数***************************") def A(): with open('./25生成器人口普查.py','r',encoding='utf-8') as f: for i in f: yield i S=A() k=eval(S.__next__()) # 转换成字典dict print(k) print(type(k)) # {'name': '上海', 'renkou': 7700} # <class 'dict'> print(k['renkou']) # 7700 # 取出所以人口数 def Q(): with open('./25生成器人口普查.py','r',encoding='utf-8') as f: for i in f: yield i n=Q() for h in n: D=eval(h) print(D['renkou']) # 7700 # 7700 # 1400 # 500 # 600 # 30000 # 222200 print("*********************1111****************************") # 求出总人数 def ff(): with open('./25生成器人口普查.py','r',encoding='utf-8') as f: for i in f: yield i v=ff() res=0 for h in v: D=eval(h) # print(D['renkou']) res+=D['renkou'] print(res) # 262400 # 求出总人数 def ff(): with open('./25生成器人口普查.py','r',encoding='utf-8') as f: for i in f: yield i v=ff() x=sum(eval(i)['renkou'] for i in v) print(x) # 描述 # sum() 方法对系列进行求和计算。 # 语法 # 以下是 sum() 方法的语法: # sum(iterable[, start]) # 参数 # iterable -- 可迭代对象,如:列表、元组、集合。 # start -- 指定相加的参数,如果没有设置这个值,默认为0。
# 模拟生产包子吃包子 # 注意:这样生产消费太消耗时间了 不严谨 # 01 生产包子 def aa (): ret=[] for x in range(20): ret.append('包子%s'%x) return ret # 02 造人来一个吃一个 def bb(res): for index,baozi in enumerate(res): print('第%s个人,吃了%s'%(index,baozi)) res=aa() bb(res) """第0个人,吃了包子0 第1个人,吃了包子1 第2个人,吃了包子2 第3个人,吃了包子3 第4个人,吃了包子4 第5个人,吃了包子5 ........"""
# 母鸡下载案例 (生成器) # 这种案例 :生成器 占空间大 效率低 # # 这个表示鸡蛋全部下出来了 def xiadan(): ret=[] for i in range(8): ret.append('鸡蛋%s'%i) return ret aa=xiadan() print(aa) # ['鸡蛋0', '鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', '鸡蛋5', '鸡蛋6', '鸡蛋7'] # 这个表示需要一个鸡蛋就下一个 def vv(): for i in range (8): yield '鸡蛋%s'%i aa=vv() BB1=aa.__next__() BB2=aa.__next__() BB3=aa.__next__() print(BB1) # 鸡蛋0 print(BB2) # 鸡蛋1 print(BB3) # 鸡蛋2
# 列表解析 aa=[] for a in range(6): aa.append("张三%s"%a) print(aa) # ['张三0', '张三1', '张三2', '张三3', '张三4', '张三5'] # 生成器表达式 c=["李四%s"%i for i in range(6)] print(c) # ['李四0', '李四1', '李四2', '李四3', '李四4', '李四5'] D=["李四%s"%i for i in range(10) if i>5] print(D) # ['李四6', '李四7', '李四8', '李四9'] # 生成器表达式 tt=("张飞%s"%i for i in range(10)) print(tt) print(tt.__next__()) print(tt.__next__()) print(next(tt)) print(next(tt)) print(next(tt)) # <generator object <genexpr> at 0x000002902A550D00> # 张飞0 # 张飞1 # 张飞2 # 张飞3 # 张飞4
# 模拟生产包子吃包子 # 注意:这样生产消费太消耗时间了 不严谨 # 01 生产包子 def aa (): ret=[] for x in range(20): ret.append('包子%s'%x) return ret # 02 造人来一个吃一个 def bb(res): for index,baozi in enumerate(res): print('第%s个人,吃了%s'%(index,baozi)) res=aa() bb(res) """第0个人,吃了包子0 第1个人,吃了包子1 第2个人,吃了包子2 第3个人,吃了包子3 第4个人,吃了包子4 第5个人,吃了包子5 ........"""
def aa(): print('开始了') yield 1 print('第一次') yield 2 print('第二次') bb=aa() res1=bb.__next__() print(res1) # 开始了 # 1 res2=bb.__next__() # print(res2) # 第一次 # 2
3.xrange和range 区别
# xrange 不会生成值 只有用的时候才会生成 # range 会直接生成一个列表 值已经生成 for a in range(1,5): print(a) # 0 # 1 # 2 # 3 # 4