• Python函数-5 生成器


    生成器
    有时候,序列或集合内的元素的个数非常巨大,如果全制造出来并放入内存,对计算机的压力是非常大的。比如,假设需要获取一个10**20次方如此巨大的数据序列,把每一个数都生成出来,并放在一个内存的列表内,这是粗暴的方式,有如此大的内存么?如果元素可以按照某种算法推算出来,需要就计算到哪个,就可以在循环的过程中不断推算出后续的元素,而不必创建完整的元素集合,从而节省大量的空间。在Python中,这种一边循环一边计算出元素的机制,称为生成器:generator。

    生成生成器:

    g = (x * x for x in range(1, 4))
    g
    <generator object <genexpr> at 0x1022ef630>
    

    可以通过next()函数获得generator的下一个返回值,这点和迭代器非常相似:

    next(g)
    1
    next(g)
    4
    next(g)
    9
    next(g)
    Traceback (most recent call last):
      File "<pyshell#14>", line 1, in <module>
        next(g)
    StopIteration
    ------------------------------------------------
    但更多情况下,我们使用for循环。
    for i in g:
        print(i)
    

    除了使用生成器推导式,我们还可以使用yield关键字。

    def createNums():
        print("----func start------")
        a,b = 0,1
        for i in range(5):
            # print(b)
            print("--1--")
            yield b
            print("--2--")
            a,b = b,a+b    # a,b = 1, 1     a,b = 1,2
            print("--3--")
        print("----func end------")
    g= createNums()
    next(g)         # 如果想得到yield的值,可以打印next(g)
    

    在 Python中,使用yield返回的函数会变成一个生成器(generator)。 在调用生成器的过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行next()方法时从当前位置继续运行。

    # 斐波那契函数
    def fibonacci(n):    
        a = 0
        b = 1
        counter = 0
        while True:
            if counter > n:
                return
            yield a             # yield让该函数变成一个生成器
            a, b = b, a + b
            counter += 1
    
    fib = fibonacci(10)           # fib是一个生成器
    print(type(fib))
    for i in fib:
        print(i, end=" ")
    

    生成器是可以循环的,相比next来说,for循环更友好

    a = createNums()
    这两种取值方式是一样的!!!
    a.__next__()
    next(a)
    
    for i in a:
        print(i)
    

    send

    def test():
        i = 0
        while i<5:
            temp = yield i
            print(temp)
            i+=1
    
    t = test()
    next(t)
    next(t)
    t.send("juran")
    next(t)
    --------------------------------------------
    t = test()
    t.send("juran")
    Traceback (most recent call last):
      File "/Users/binbin/Desktop/Python/demo.py", line 179, in <module>
        t.send("juran")
    TypeError: can't send non-None value to a just-started generator
    
    如何解决这个错误?
    > next(t)
      t.send("juran")
      
    > send(None)
    

    生成器的应用
    实现多任务

    def test1():
        while True:
            print("--1--")
            yield None
            
    def test2():
        while True:
            print("--2--")
            yield None
    
    t1 = test1()
    t2 = test2()
    while True:
        next(t1)
        next(t2)
    
  • 相关阅读:
    Java I/O
    iOS AppsFlyer的使用注意事项
    Star Schema and Snowflake Schema
    SSB基准测试
    ES Route
    CPS(Cyber-Physical Systems)白皮书-摘选
    蓄电池放电容量与环境温度的关系
    时间序列分析(二)
    时间序列分析(一)
    IndexR
  • 原文地址:https://www.cnblogs.com/sakura579/p/12397549.html
Copyright © 2020-2023  润新知