迭代器,生成器,协成函数

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")

  

原文地址:https://www.cnblogs.com/amiee-785563694/p/6786639.html