【25】Python生成器generat

发布时间:2019-09-16 07:39:23编辑:auto阅读(1985)

    列表生成式
    一个小题目:将里列表[0,1,2,3]里面的数值都加1.
    方法1:

    a=[0,1,2,3]
    b=[]
    for i in range(len(a)):
        b.append(i+1)
    a=b
    print(a)

    方法2:

    a = [1,3,4,6,7,7,8]
    for index,i in enumerate(a):
        a[index] +=1
    print(a)

    方法3:

    a=[0,1,2,3,4]
    a=map(lambda x:x+1,a)
    print(a)
    for i in a:
        print(i)

    方法4:(列表生成式)

    a=[i+1 for i in range(10)]
    print(a)

    看出了什么没有?没错,同样的功能,实现的代码越来越精简。

    进入正题:生成器
    通过列表生成式,我们可以直接创建一个列表。但是,受内存限制,列表的容量肯定有限。如果创建大量数据,结果只用到几条,那也是相当占用空间的。
    所以列表元素按照某种算法推算出来,那我们是否可以在循环的过程中不断的推算出后续的元素呢?这样可以节约大量空间。在python中,这种一边循环一边计算的机制,成为生存器:generator。
    创建生成器有很多种方法,最简单的方法就是把一个列表[]改成(),就创建了一个generator:

    g=(i+1 for i in range(10))
    print(g)

    运行的结果就是根据算法生成的,只有在循环调用的时候,才会显示。

    l=[x+1 for x in range(10)]
    print(l)

    列表会显示所有数据。而生成器generator需要通过循环或者next()函数调用才能算出来。
    直到计算到最后一个元素,没有更多的元素时,会抛出异常StopIteration的错误。

    下面可以用函数实现:比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
    1, 1, 2, 3, 5, 8, 13, 21, 34, ...

    def fib(max):
        n ,a,b =0,0,1
        while n <max:
            print(b)
            a,b=b,a+b
            n=n+1
        return "done"
    print(fib(10))

    而实现生成器的转换,只需要修改一步。将print(b),改成yield b即可

    def fib(max):
        n,a,b=0,0,1
        while n<max:
            # print(b)
            yield b  ##有yield存在时就不叫函数了,而叫生成器
            a,b=b,a+b
            n=n+1
        return "done"
    print(fib(10))
    f=fib(10)
    g=fib(6)
    while True:
        try:
            x=next(g)
            print("g",x)
        except StopIteration as e:  #异常起个名字叫 e
            print("Generator return value:",e.value)
            break
    # print(f.__next__())
    # print(f.__next__())
    # print(f.__next__())
    # print(f.__next__())
    # print(f.__next__())
    # print(f.__next__())
    # print(f.__next__())
    # print(f.__next__())
    # print(f.__next__())
    # print(f.__next__())
    # print(f.__next__())

    生成器并行运行

    import time
    def consumer(name):
        print("%s eat!"%name)
        while True:
            baozi=yield #yield没有返回值空的
            print("包子%s来了,被%s吃了"%(baozi,name))
    
    # c=consumer("alex")
    # c.__next__()
    # b1="韭菜馅"
    # b2="肉馅"
    # c.send(b1) ##调用b1,同时给传值
    # c.__next__()
    
    #携程(nginx异步处理)
    def producer(name):
        c1=consumer("A")
        c2=consumer("B")
        c1.__next__()
        c2.__next__()
        print("准备包子!!!")
        for i in range(10):
            time.sleep(2)
            print("做一个,两人分着吃!")
            c1.send(i)
            c2.send(i)
    producer("alex")

关键字