deffunc():print("我是第一个段")
a =yield123print(a)# 执行第一个.__next__()时,这里是没执行的print("周杰伦是第二段")
b =yield456print(b)# ??print("林俊杰是第三段")
c =yield789print(c)print("李宗盛是最后一个段")yield79# 最后收尾一定是yield# 只要记住 是停在 yield的位置,send 返回也是在 yield的位置
g = func()print(g.__next__())# 如果要用send()开头的话,必须设置为None# 也可以写成:print(g.send(None))print(g.send("煎饼果子"))print(g.send("韭菜盒子"))print(g.send("锅包肉"))# 输出结果:"""
我是第一个段
123
煎饼果子
周杰伦是第二段
456
韭菜盒子
林俊杰是第三段
789
锅包肉
李宗盛是最后一个段
79
"""defeat():print("我吃什么啊")
a =yield"馒头"print("a=",a)
b =yield"鸡蛋灌饼"print("b=",b)
c =yield"韭菜盒子"print("c=",c)yield"GAME OVER"
gen = eat()# 获取生成器
ret1 = gen. __next__()print(ret1)# 馒头
ret2 = gen.send("胡辣汤")print(ret2)
ret3 = gen.send("狗粮")print(ret3)
ret4 = gen.send("猫粮")print(ret4)
>>>计算移动平均值(1)defaverager():
total =0.0
count =0
average =NonewhileTrue:
term =yield average
total += term
count +=1
average = total/count
g_avg = averager()next(g_avg)print(g_avg.send(10))print(g_avg.send(30))print(g_avg.send(5))
>>>计算移动平均值(2)_预激协程的装饰器
definit(func):# 在调用被装饰生成器函数的时候首先用next激活生成器definner(*args,**kwargs):
g = func(*args,**kwargs)next(g)return g
return inner
@init
defaverager():
total =0.0
count =0
average =NonewhileTrue:
term =yield average
total += term
count +=1
average = total/count
g_avg = averager()# next(g_avg) 在装饰器中执行了next方法print(g_avg.send(10))print(g_avg.send(30))print(g_avg.send(5))
import time
deftail(filename):
f =open(filename)
f.seek(0,2)# 从文件末尾算起whileTrue:
line = f.readline()# 读取文件中新的文本行ifnot line:
time.sleep(0.1)continueyield line
tail_g = tail('tmp')for line in tail_g:print(line)
yield from
defgen1():for c in'AB':yield c
for i inrange(3):yield i
print(list(gen1()))defgen2():yieldfrom'AB'yieldfromrange(3)print(list(gen2()))yieldfrom
推导式(生成式/解析式)
推导式: 用一句话来生成一个列表
列表推导式
lst =[]for i inrange(1,16):
lst.append("python"+str(i))print(lst)# 列表推导式:
lst =["python"+str(j)for j inrange(1,16)]print(lst)# 语法: [结果 for循环 判断]
lis=[i for i inrange(10)if i%2==1]print(lis)>>>100以内能被3整除的数的平方
lst =[i*i for i inrange(100)if i%3==0]print(lst)>>>寻找名字中带有两个e的人的名字
names =[['Tom','Billy','Jefferson','Andrew','Wesley','Steven','Joe'],['Alice','Jill','Ana','Wendy','Jennifer','Sherry']]# lis=[]# for el in names:# for i in el:# if i.count("e")>=2:# lis.append(i)# print(lis)
lst=[name for el in names for name in el if name.count("e")>=2]print(lst)
字典推导式
>>>给一个列表[11,22,33,44] 需要变成 字典{0:11,1:22,2:33,3:44}
li=[11,22,33,44]
dic={}for i inrange(len(li)):for j inrange(len(li)):if i==j:
dic[i]=li[i]print(dic)# 推导式做法:
dic={i:li[i]for i inrange(len(li))if i<2}print(dic)#最终的结果是要拿到键值对,键值对 分别是列表的索引和索引对应的值# 字典推导式
语法:{k:v for循环 条件筛选}>>>将字典的键值对调换顺序
dic ={"jj":"林俊杰","jay":"周杰伦","zs":"赵四","ln":"刘能"}
d(dic)={v:k for k,v in dic.items()}print(dic)
set集合推导式
li=[1,1,2,3,3,5,6,6]
s={el for el in li}#去重print(s)
生成器表达式 / 推导式
tu =(i for i inrange(10))# 没有元组推导式;这个叫生成器表达式print(tu)# 生成器print(tu.__next__())print(tu.__next__())...
lst =[i for i inrange(10)]# 列表推导式print(lst)
gen =(i for i inrange(10))# 生成器, 惰性机制# 使用生成器的优点:
延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,
这对于大数据量处理,将会非常有用。
# 列表解析sum([i for i inrange(100000000)])# 内存占用大,机器容易卡死# 生成器表达式sum(i for i inrange(100000000))# 几乎不占内存
易错题/难题
# 生成器函数deffunc():print(111)yield222
g = func()# 获取生成器
g1 =(i for i in g)# 生成器
g2 =(i for i in g1)# 生成器print(list(g))# ??? [222] 源头.从源头把数据拿走了print(list(g1))# ??? [] 这里执行的时候. 源头已经没有数据print(list(g2))# ??? [] 这里也没有值了# 输出结果:111 [222] [] []# 变形deffunc():print(111)yield222yield333
g = func()# 获取生成器
g1 =(i for i in g)# 生成器
g3 = func()# 获取生成器,都从生成器函数里拿值
g2 =(i for i in g3)# 生成器print(list(g))# [222,333] 源头. 从源头把数据拿走了print(list(g1))# [] 这里执行的时候. 源头已经没有数据print(list(g2))# [222,333]这里有值了,因为g3作为源头是一个新的生成器# 再变形:deffunc():print(111)yield222yield333
g = func()# 获取生成器
g1 =(i for i in g)# 生成器
g3 = func()# 获取生成器,都从生成器函数里拿值
g2 =(i for i in g3)# 生成器print(g.__next__())#__next__()只拿yield里的一个,所以是222print(list(g1))#是全装,g1 通过g 来拿,但是因为yield里,只剩下一个[333]了print(list(g2))#是全装,g2通过 g3来拿,g3会获取生成器,所以能拿到全部的[222,333]# 输出结果:111 222 [333] 111 [222, 333]# 生成器问题难题defadd(a, b):return a + b
deftest():for r_i inrange(4):yield r_i
g = test()# 生成器,没取值,范围0,1,2,3for n in[2,10]:# n=2 , n=10
g =(add(n, i)for i in g)print(list(g))# n循环时,分别代入# 输出结果为:2,3,4,5 [],前面取完后,后面取不到值
————————
defadd(a, b):return a + b
deftest():for r_i inrange(4):yield r_i
g = test()# 生成器,没取值,范围0,1,2,3for n in[2,10]:# n=2 , n=10
g =(add(n, i)for i in g)print(list(g))# n 循环完,再代入# 拆分:
n=2
g =(add(n, i)for i in g)# 生成器,没有取值
n=10
g =(add(n, i)for i in g)# 将这个g替换
g =(add(n, i)for i in(add(n, i)for i in g))# 将n=10带入
g =(add(10, i)for i in(add(10, i)for i in (0,1,2,3)))print(list(g))# 这个取值了,并且是一次性装入list中print(list(g))# [] 取完了# 输出结果为:[20,21,22,23]# 总之生成器 执行流程时,只要没到 __next__()和 list()之类的遍历,都不会取到值
defdemo():for i inrange(4):yield i
g=demo()
g1=(i for i in g)
g2=(i for i in g1)print(list(g1))print(list(g2))
协程应用:grep -rl /dir tail&grep
import os
definit(func):defwrapper(*args,**kwargs):
g=func(*args,**kwargs)next(g)return g
return wrapper
@init
deflist_files(target):while1:
dir_to_search=yieldfor top_dir,dir,files in os.walk(dir_to_search):forfilein files:
target.send(os.path.join(top_dir,file))
@init
defopener(target):while1:file=yield
fn=open(file)
target.send((file,fn))
@init
defcat(target):while1:file,fn=yieldfor line in fn:
target.send((file,line))
@init
defgrep(pattern,target):while1:file,line=yieldif pattern in line:
target.send(file)
@init
defprinter():while1:file=yieldiffile:print(file)
g=list_files(opener(cat(grep('python',printer()))))
g.send('/test1')