zoukankan      html  css  js  c++  java
  • 6 生成器 yield 协程

    1.生成器

    ----> 1 b = [x*2 for x in range(100000000000)]
    
    MemoryError: 

    想生成一个存放很多数据的列表,但是又不想内存占用太多

    每次用一个生成一个,最好

      2)列表生成器:生成多个值,每次生成1个

    In [29]: c = (x*2 for x in range(10))
    
    In [30]: c
    Out[30]: <generator object <genexpr> at 0x7f8b5c0c6960>
    
    
    In [31]: next(c)
    Out[31]: 0
    
    In [32]: next(c)
    Out[32]: 2
    
    In [40]: next(c)
    Out[40]: 18
    
    In [41]: next(c)                   #迭代器没有数据就出现异常了
    ---------------------------------------------------------------------------
    StopIteration                             Traceback (most recent call last)
    <ipython-input-41-73b012f9653f> in <module>()
    ----> 1 next(c)

    2.斐波那契数列

      1)版本1:a,b = b,a+b

    def creat_num():
        a,b = 0,1
    
        for i in range(5):
            print(b)
            a,b = b,a+b
    
    creat_num()
    
    
    1
    1
    2
    3
    5

      2)版本2:生成器 yield b

     def creat_num():
         a,b = 0,1
         
         for i in range(5):
             yield b
             a,b = b,a+b
         
     creat_num()

      3)版本3:当成模块导入

      可以通过 next() 函数获得生成器的下一个返回值:

    def creat_num():
        print("--start---")
        a,b = 0,1
    
        for i in range(5):
            print("--1--")
            yield b               #每次next执行到yield这里停止
            print("--2---")
            a,b = b,a+b
            print("--3--")
        print("--end---")
    In [4]: a = creat_num()
    
    In [5]: a
    Out[5]: <generator object creat_num at 0x7facd60b5a98>
    
    In [6]: next(a)
    --start---
    --1--
    Out[6]: 1
    
    In [7]: next(a)
    --2---
    --3--
    --1--
    Out[7]: 1
    
    In [8]: next(a)
    --2---
    --3--
    --1--
    Out[8]: 2

      4)版本4:next(a)  和  a.__next__()

    def creat_num():
        print("--start---")
        a,b = 0,1
    
        for i in range(5):
            print("--1--")
            yield b
            print("--2---")
            a,b = b,a+b
            print("--3--")
        print("--end---")
    
    #创建了1个生成器对象
    a = creat_num()
    
    ret = next(a)  #让a这个生成器对象开始执行,如果第一次执行,就从create_num开始部分执行
                  #如果是之前已经执行过了,就从上一次停止的位置开始执行
    ret = next(a) 
    ret = next(a) 

      

    def creat_num():
        print("--start---")
        a,b = 0,1
    
        for i in range(5):
            print("--1--")
            yield b
            print("--2---")
            a,b = b,a+b
            print("--3--")
        print("--end---")
    
    #创建了1个生成器对象
    a = creat_num()
    
    ret = a.__next__()
    print(ret)
    
    #注意:
    #next(a)
    #a.__next__()
    #以上两种方式是一样的

      5)版本5:循环取出生成器的值

    def creat_num():
        print("--start---")
        a,b = 0,1
    
        for i in range(5):
            print("--1--")
            yield b
            print("--2---")
            a,b = b,a+b
            print("--3--")
        print("--end---")
    
    #创建了1个生成器对象
    a = creat_num()
    
    for i in a:                   #循环取出值
        print(i)
    --start---
    --1--
    1
    --2---
    --3--
    --1--
    1
    --2---
    --3--
    --1--
    2
    --2---
    --3--
    --1--
    3
    --2---
    --3--
    --1--
    5
    --2---
    --3--
    --end---

    3。send(‘haha’)

    例子:执行到yield时,gen函数作用暂时保存,返回i的值;temp接收下次c.send("python"),send发送过来的值,c.next()等价c.send(None)

    In [10]: def test():
       ....:     i = 0
       ....:     while i < 5:
       ....:         temp = yield i 
       ....:         print(temp)
       ....:         print(i)
       ....:         i += 1
    In [20]: t =test()
    
    In [21]: t.__next__()
    Out[21]: 0                        #yield i 的返回值  相当于return i 
    
    In [22]: t.__next__()
    --1 None
    --2 0
    Out[22]: 1
    
    In [23]: t.__next__()
    --1 None
    --2 1
    Out[23]: 2
    
    In [24]: t.__next__()
    --1 None
    --2 2
    Out[24]: 3
    
    In [25]: t.send('haha')   #相当于yield i = haha  ,temp =haha
    --1 haha
    --2 3
    Out[25]: 4            #到yield 停止  yield i  返回return i

       2)第一次send(None)

    In [26]: t = test()
    
    In [27]: t.send('lala')
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-27-e48ba033e48c> in <module>()
    ----> 1 t.send('lala')
    
    TypeError: can't send non-None value to a just-started generator
      #直接send 出现异常
    In [29]: t.send(None)    #第一次相当于t.__next__()
    Out[29]: 0
    
    In [30]: t.send('--lala')
    --1 --lala
    --2 0
    Out[30]: 1

     4.yield 多任务  协程

    def test1():
        while True:
            print('===1')
            yield None
    
    def test2():
        while True:
            print('---2')
            yield None
    
    t1 =test1()
    t2 = test2()
    while True :
        t1.__next__()
        t2.__next__()
    ### 运行结果
    ===1
    ---2
    ===1
    ---2
    ===1
    ---2
    ===1
    ---2
    ===1
    ---2
    ===1
    ---2

    5.总结

    生成器是这样一个函数,它记住上一次返回时在函数体中的位置。对生成器函数的第二次(或第 n 次)调用跳转至该函数中间,而上次调用的所有局部变量都保持不变。

    生成器不仅“记住”了它数据状态;生成器还“记住”了它在流控制构造(在命令式编程中,这种构造不只是数据值)中的位置。

    生成器的特点:

    1. 节约内存
    2. 迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的
  • 相关阅读:
    hihoCoder #1176 : 欧拉路·一 (简单)
    228 Summary Ranges 汇总区间
    227 Basic Calculator II 基本计算器II
    226 Invert Binary Tree 翻转二叉树
    225 Implement Stack using Queues 队列实现栈
    224 Basic Calculator 基本计算器
    223 Rectangle Area 矩形面积
    222 Count Complete Tree Nodes 完全二叉树的节点个数
    221 Maximal Square 最大正方形
    220 Contains Duplicate III 存在重复 III
  • 原文地址:https://www.cnblogs.com/venicid/p/7927849.html
Copyright © 2011-2022 走看看