zoukankan      html  css  js  c++  java
  • 迭代器,生成器,协成函数

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

      

  • 相关阅读:
    NOIP2018 复赛提高组一等奖获奖名单
    JZOJ 5222. 【GDOI2018模拟7.12】A(权值线段树)
    NOIP2018 提高组复赛成绩-广东
    NOIP2018 总结
    NOIP 复赛注意事项
    JZOJ 5168. 冲击哥(贪心)
    数据库
    估计理论简介
    KMP
    从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
  • 原文地址:https://www.cnblogs.com/amiee-785563694/p/6786639.html
Copyright © 2011-2022 走看看