四. 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
# 获取移动平均值
# 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)
# 监听文件用户文件输入
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

 

 

 


posted @ 2019-05-11 16:37  supreme9999  阅读(437)  评论(0编辑  收藏  举报