zoukankan      html  css  js  c++  java
  • python yield

    一。深入研究

    >>> def get_0_1_2():
    ...   yield 0
    ...   yield 1
    ...   yield 2
    ...
    >>> get_0_1_2
    <function get_0_1_2 at 0x00B2CB70>       #函数类型
    
    >>> generator = get_0_1_2()
    >>> generator
    <generator object get_0_1_2 at 0x00B1C7D8>  #生成器
    
    >>> generator.next()    #第一次调用生成器的next方法时,生成器才开始执行生成器函数(而不是构建生成器时),直到遇到yield时暂停执行
    0
    >>> generator.next()    #之后每次调用生成器的next方法,生成器将从上次暂停执行的位置恢复执行生成器函数,直到再次遇到yield时暂停
    1
    >>> generator.next()
    2

    >>> generator.next() #当调用next方法时生成器函数结束(遇到空的return语句或是到达函数体末尾),则这次next方法的调用将抛出StopIteration异常
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration

    因为直接调用next()到最后会抛出异常,所以一般使用for循环输出结果

    >>> def test_return():
    ...      yield 4
    ...      return 0
    ...
      File "<stdin>", line 3
    SyntaxError: 'return' with argument inside generator

      作为生成器,因为每次迭代就会返回一个值,所以不能显示的在生成器函数中return 某个值,包括None值也不行,否则会抛出“SyntaxError”的异常,

    但是在函数中可以出现单独的return,表示结束该语句。 

    二。控制生成器

    1.变量控制

     class Bank(): # 创建银行,构建ATM机,只要没有危机,就可以不断地每次从中取100
        crisis = False
        def create_atm(self):
            while not self.crisis:
                yield "$100"

    2. send: Resumes the generator and "sends" a value that becomes the result of the current yield-expression

    def consumer():
        print "consumer start..."
        result = None
        while True:
            s = yield result
            result = s.split(",")
    
    c = consumer()  
    #不调用则出错:TypeError: can't send non-None value to a just-started generator
    print c.send(None)   # send(None) 或 next()启动协程
    
    print c.send("a,b")  # 向协程发送消息
    print c.send("c,d")
    c.close()           # 关协程
    # print c.send("e,f")  # 无法向已关闭的协程发送消息。

    3.

    def consumer():
        while True:
            d = yield
            if not d :break
            print "consumer: ", d
    
    c = consumer() #创建消费者
    c.send(None)   #启动消费者
    c.send(1)      #生产数据,并提供给消费者
    c.send(2)
    c.send(3)
    c.close()

    三。示例

    1.斐波那契数列

    >>> def fibonacci():
    ...   a = b = 1
    ...   yield a
    ...   yield b
    ...   while True:
    ...     a, b = b, a+b
    ...     yield b
    ...
    >>> for num in fibonacci():
    ...   if num > 100: break
    ...   print num,
    ...
    1 1 2 3 5 8 13 21 34 55 89

    看到while True可别太吃惊,因为生成器可以挂起,所以是延迟计算的,无限循环并没有关系。

    2.读大文件

    如果直接对文件对象调用 read() 方法,会导致不可预测的内存占用。好的方法是利用固定长度的缓冲区来不断读取文件内容。

    def read_file(path):
        size = 1024
        with open(path,'r') as f:
            while True:
                block = f.read(SIZE)
                if block:
                    yield block
                else:
                    return
  • 相关阅读:
    洛谷 P1550 [USACO08OCT]Watering Hole G(最小生成树||超级源点)
    洛谷 P2168 [NOI2015]荷马史诗(Huffman树|编码)
    洛谷 P5658 括号树(DFS)
    用堆来求中位数
    c++各种输入输出(文件输入输出,标准输入输出,一些字符串)
    Hello,world!
    【NOIP2013】花匠
    【洛谷习题】最长上升子序列
    【NOIP2014】联合权值
    【NOIP2014】飞扬的小鸟
  • 原文地址:https://www.cnblogs.com/yuyutianxia/p/4116040.html
Copyright © 2011-2022 走看看