zoukankan      html  css  js  c++  java
  • 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)
    
  • 相关阅读:
    HDU 1850 Being a Good Boy in Spring Festival
    UESTC 1080 空心矩阵
    HDU 2491 Priest John's Busiest Day
    UVALive 6181
    ZOJ 2674 Strange Limit
    UVA 12532 Interval Product
    UESTC 1237 质因子分解
    UESTC 1014 Shot
    xe5 android listbox的 TMetropolisUIListBoxItem
    xe5 android tts(Text To Speech)
  • 原文地址:https://www.cnblogs.com/sakura579/p/12397549.html
Copyright © 2011-2022 走看看