迭代器,生成器,协成函数
1 迭代器
可迭代对象,可使用.iter方法
2 生成器
在函数体里面使用Yield,并且把yield作为一个语句形式存在
本身就是迭代器,并且具备.next方法
#return只能返回一个值,yiled能返回多次值 #yiled能把一个函数变成一个生成器 #yiled能保存当前程序的运行状态 #yiled能作为一个语句形式存在 yield n #yiled能作为一个表达式形式存在 n=yield 可以用send()赋值给n from collections import Iterator def foo(): print("======1") yield 1 print("======2") yield 2 print("======3") yield 3 g=foo() print(isinstance(g,Iterator)) # print(next(g)) #next()触发函数的运行,到yield的时候停止 # print(next(g)) for i in g: #g只是一个生成器,只能执行一次 print(i) """ True ======1 1 ======2 2 ======3 3 """ # print(next(g))
""" 1.函数在执行的时候,如果找不到yield的时候,会报StopIterator,for循环不报错的原因是因为 是因为for循环的源码中帮我们捕捉异常 2.用while来遍历,需要我们自定义异常处理 """ def countdown(x): while x<10: yield x x+=1 g=countdown(5) # for i in g: # print(i) # while True: # try: # print(next(g)) # except StopIteration: # break # def func(): # n=0 # while True: # yield n # n+=1 # # f=func() #演示动态监测文件的变化 #tail -f a.txt | grep "error" """ 思路:tail -f 目的是想要监听文件最后追加一行的内容 方法:先打开一个文件r的模式,光标移到到最后一行有新的内容添加时就打印这行内容 """ import time def tail(file_path): with open(file_path,"r",encoding="utf-8") as f: f.seek(0,2) #光标移到文件最后的一行的开头 while True: #必须一直读,不然写进去的内容,读取不到 time.sleep(0.3) line=f.readline() #读光标当前的整行 if not line:continue else: yield line #end=""表示会去除写进每行最后的换行符 def grep(pattern,lines): #两个参数,一个是过滤“error”,跟生成器 for line in lines: #遍历生成器 if pattern in line: yield line g=tail("a.txt") g2=grep("error",g) #使用生成器,next触发执行g2生成器 for i in g2: print(i)
3 协成函数
send()传值必须是元组形式
#把yield作为表达式形式 n=yield def dec(func): def wapper(*arge,**kwargs): res=func(*arge,**kwargs) next(res) return res return wapper @dec def eater(name): print("%s start to eat"%name) while True: food=yield print("%s get %s ,开始吃了"%(name,food)) g=eater("egon") # g=eater("egon") #有yield表示该函数是哟个生成器,必须next()才能执行 # next(g) #走到yield的地方暂停 # g.send("包子") #send也具备next()方法,可以为当前暂停的yield地方传值 # next(g)
4.练习
4.1 爬网页
#爬网页 from urllib.request import urlopen def geturl(): while True: url=yield res=urlopen(url).read() return res g=geturl() next(g) res=g.send("http://www.baidu.com") print(res)
4.2面向过程编写查找文件
#面向过程 #查询目录下文件中包含“xxx”字符串的,并且打印出该文件的路径 #grep -rl ""python" c:\egon """ 思路: 1.找到文件的绝对路径 2.打开文件,获取文件句柄 3.读取文件内容 4.过滤这行文件是否含有“python” 5.打印文件的绝对路径 """ import os def foo(func): def wapper(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return wapper "找到一个就往下面发一个" @foo def search(target): #1.传一个生成器 "找到路径下的所有文件路径" while True: file_dir=yield g=os.walk(file_dir) for i in g: for j in i[2]: file_path=i[0]+"\\"+j target.send(file_path) @foo def open_file(target): "打开文件" while True: file_path=yield with open(file_path,"r",encoding="utf-8") as f: target.send((f,file_path)) @foo def cat_file(target): "读取文件" while True: f,file_path=yield for line in f: target.send((line,file_path)) @foo def grep(patter,target): "过滤文件" while True: line,file_path=yield if patter in line: target.send(file_path) @foo def print_file(): "打印文件" while True: file_path=yield print(file_path) "search需要一个参数生成器open_file()" \ "open_file()需要一个参数生成器" \ g=search(open_file(cat_file(grep("python",print_file())))) #next(g) #协成函数的初始化,必须先nest,执行到yield,在send,用装饰器做 g.send("d:\\egon")