• 生成器


    定义:函数内含有yield关键字的函数运行结果就是生成器,生成器本质上就是迭代器

       生成器本身不可以运行,要运行必须通过next()触发运行,for循环中带有next,while循环也要加了next()才能迭代

       迭代器就是为了好多没有索引的可迭代对象搞出来的,也只有通过next()才能读出来,结合上边那句话理解

    1、重点

      生成器,要生成,首先想到return

      生成器是迭代器,是可迭代对象,是生成器

      迭代器是迭代器,是可迭代对象

      可迭代对象指示可迭代对象

    2、生成器与return有何区别?

      生成器就是一个函数的内存地址,这个函数内包含有yield这个关键字

      return只能返回一次函数就彻底结束了,而yield能返回多次返回值

      yield和return一样能返回任意值,多个值也是以元组返回

      再循环中的yield是第一次的终点,以后每次的起点和终点,

    3、yield干了哪些事?

      yield把函数变成(生成器,生成器就是)迭代器相当于yield把iter()和next()封装到函数内部

      用return返回只能返回一次,而yield返回多次

      函数在暂停以及继续下一次运行时的状态由yield保存

      yield有两种形式,一种是语句形式(生成器函数)就是和return差不多的,另一个是表达式形式(协程函数其实也是生成器原理)

    4、生成器理解示例

    def test():
        print("first")
        yield 1#return 1
        yield 2
        yield 3
    g=test()#g是生成器,是可迭代对象是迭代器
    print(g)
    next(g)
    next(g)#next超出范围还是会报错
    print(next(g))#next可以触发迭代器往下走
    #运行原理如下:
    #print(next(g))
    #print(next(test())
    #运行test()先print("first")然后碰到yield返回1
    #然后结束运行
    
    #用for循环输出g
    for i in g:#
        print(i)
    
    def countdown(n):
        print("start")
        while n>0 :
            yield n
            n-=1
        print("done")
    g=countdown(5)#g是生成器,是可迭代对象是迭代器
    #用next一步一步输出g
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))#超出范围,打印done后报错StopIteration
    # 用for循环g
    for i in g:
        print(i)
    #用while循环输出g
    while True:
        try:
            print(next(g))
        except StopIteration:
            break
    #因为迭代器是一次性的,所以上边三种循环输出方式只能同时用一种

    5、利用生成器的特点实现tail -f /tmp/a.txt |grep 'error'的功能

    #/usr/bin/env python
    #定义阶段:定义两个生成器函数
    import time
    def tail(file_path):
        with open(file_path,encoding="utf8") as f:
            f.seek(0,2)
            while True:
                line=f.readline()
                if not line:
                    time.sleep(0.5)
                    continue
                else:
                    yield line
    def grep(pattern,target):
        for line in target:
            if pattern in line:
                yield line
    #调用阶段:得到两个生成器对象
    g1=tail("/tmp/a.txt")
    g2=grep("error",g1)
    #next触发执行改g2生成器函数 ,用for循环或者while循环来
    for i in g2:
        print(i)
    

    6.关于生成器的一道经典面试题

    def add(s, x):
        return s + x
    def generator():
        for i in range(4):
            yield i
    base = generator()
    for n in [1, 11]:
        base = (add(i, n) for i in base)
    print(list(base))
    
    '''
    生成器表达式在没有被next的时候它只是一个表达式,只是一个表达式,不是具体的值
    当for n in [1, 11]运行完后,n的值就为11了,这个题可以写成以下这种
    '''
    
    def add(s, x):
        return s + x
    def generator():
        for i in range(4):
            yield i
    base = generator()
    n=1
    base = (add(i, n) for i in base)
    n=11
    base = (add(i, n) for i in base)
    print(list(base))
    

      

  • 相关阅读:
    Thinkphp 边学边用验证码无意间犯的错
    如何计算团队成员贡献分
    禅道使用之项目经理篇
    禅道使用之开发团队篇
    黑盒测试实践作业进度报告(周日)
    黑盒测试实践作业进度报告(周六)
    禅道使用之产品经理篇
    第1周小组博客作业——关于禅道测试管理的总结
    禅道介绍与环境搭建
    一个工作了5年的程序员,将来在哪里?
  • 原文地址:https://www.cnblogs.com/wuyongqiang/p/6694964.html
Copyright © 2020-2023  润新知