zoukankan      html  css  js  c++  java
  • 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。

  • 相关阅读:
    HBase with MapReduce (MultiTable Read)
    HBase with MapReduce (SummaryToFile)
    HBase with MapReduce (Summary)
    HBase with MapReduce (Read and Write)
    HBase with MapReduce (Only Read)
    Hbase中的BloomFilter(布隆过滤器)
    HBase的快照技术
    How To Use Hbase Bulk Loading
    Cloudera-Manager修改集群的IP
    Java中的HashSet和TreeSet
  • 原文地址:https://www.cnblogs.com/greatkyle/p/6694302.html
Copyright © 2011-2022 走看看