• python编程之生成器(generator)


    1、生成器介绍

    首先请确信,生成器就是一种迭代器。生成器拥有next方法并且行为与迭代器完全相同,这意味着生成器也可以用于Python的for循环中。

    2、生成器函数

      1)、自定义生成器

     1 def generator1():
     2     yield 1
     3     yield 2
     4     yield 3
     5 
     6 
     7 g = generator1()
     8 print(next(g))
     9 print(next(g))
    10 print(next(g))
    #执行结果
    1
    2
    3
    

      

    我们需要注意的是:第一次调用生成器的next方法时,生成器才开始执行生成器函数(而不是构建生成器时),直到遇到yield时暂停执行(挂起),并且yield的参数将作为此次next方法的返回值;

    1 >>> def gen():
    2 ...     yield 1
    3 ...     yield 2
    4 ... 
    5 >>> g = gen()
    6 >>> type(g)
    7 <class 'generator'>  

     当调用next方法时生成器函数结束,再次调用next方法将抛出StopIteration异常。(即for循环的终止条件)

    1 >>> next(g)
    2 1
    3 >>> next(g)
    4 2
    5 >>> next(g)
    6 Traceback (most recent call last):
    7   File "<stdin>", line 1, in <module>
    8 StopIteration

    其他补充知识:

    1、生成器带参数

     1 >>> def counter(start=0):
     2 ...     while True:
     3 ...         yield start
     4 ...         start +=1
     5 ... 
     6 >>> count = counter()
     7 >>> next(count)
     8 0
     9 >>> next(count)
    10 1
    11 >>> next(count)
    12 2
    13 >>> next(count)
    14 3
    协同程序(coroutine)

    1、可以方便地挂起、恢复,并且有多个入口点和出口点;

    2、多个协同程序间表现为协作运行,如A的运行过程中需要B的结果才能继续执行。

    协程的特点决定了同一时刻只能有一个协同程序正在运行。得益于此,协程间可以直接传递对象而不需要考虑资源锁、或是直接唤醒其他协程而不需要主动休眠,就像是内置了锁的线程。在符合协程特点的应用场景,使用协程无疑比使用线程要更方便。

    协程函数的例子:

    文件a.txt,打印出所有含有“apple”的行

    apple 10 3
    iphone 4000 1
    macbook 3000 2
    chicken 10 3
    apple 11 22
    apple 20 23
     1 def cat(file_path):#定义cat函数寻找文件读取内容
     2     with open(file_path) as f:
     3         for line in f:
     4             if not line:
     5                 continue
     6             else:
     7                 yield line
     8 
     9 def grep(source, keywords):#判断函数,是否含有相应的关键字
    10     if keywords in source:
    11         yield source
    #执行代码
    1
    source1 = cat("a.txt") #生成器 2 print(source1) 3 for i in source1: 4 g1 = grep(i,"apple") 5 6 for i in g1: 7 print(i, end="")
    #执行结果
    <generator object cat at 0x1011030f8> apple 10 3 apple 11 22 apple 20 23

     生成器中的send(value)方法。send是除next外另一个恢复生成器的方法。此时yield语句变成了yield表达式,这意味着yield现在可以有一个值,而这个值就是在生成器的send方法被调用从而恢复执行时,调用send方法的参数

    1 from urllib.request import urlopen
    2 
    3 def get():
    4     while True:
    5         url = yield 
    6         res = urlopen(url).read()
    7         print(res)
    1 g = get()
    2 next(g)
    3 g.send("http://www.sina.com.cn")

    注意:

      1、调用send传入非None值前,生成器必须处于挂起状态,否则将抛出异常。未启动的生成器仍可以使用None作为参数调用send。 
      2、如果使用next恢复生成器,yield表达式的值将是None。

  • 相关阅读:
    Java 中的传值与传引用
    UML中的类图及类图之间的关系
    [转]多线程下单例模式惰性加载
    中缀表达式转后缀表达式,Java实现
    自用Intellij IDEA设置
    [转]JavaScript将MyBatis打印的日志转化为可执行sql
    SpringBoot利用poi导出excel下载
    详解 HiveUDF 函数
    最全的 Java 知识总结- Github 日增 10 star
    最好用的 Kafka Json Logger Java客户端,赶紧尝试一下
  • 原文地址:https://www.cnblogs.com/greatkyle/p/6694302.html
Copyright © 2020-2023  润新知