迭代器,生成器,协成函数
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")
浙公网安备 33010602011771号