• python 基础 day04—列表生成器/生成器


    列表生成式

    a=[i*2 for i in range(10)]
    print(a)
    #==> [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

    若不用列表生成式,可用以下方法达到以上效果

    for i in range(10):
        a.append(i*2)
    
    print(a)

    比较复杂!

    生成器

    1.只有在调用时才会生成相应的数据

    2.只记录当前位置

    3.只有一个__next__方法

    创建一个生成器,只要把一个列表生成式的[]改成(),就创建了一个generator

    ( i*2 for i in range(10) )

    现在,用函数写斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到

    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))
    
    结果:
    1
    1
    2
    3
    5
    8
    13
    21
    34
    55
    done #所有消息均输出完毕,因此抛出异常消息 

    可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

    要把fib函数变成generator,只需要把print(b)改为yield b就可以了

    通过函数做成一个生成器

    def fib(max):
        n,a,b=0,0,1
        while n < max:
            yield(b)   #yield的作用是保存当前状态,然后返回
            a,b=b,a+b
            n=n+1
        return 'done'
    
    f= fib(10)
    print(a)
    
    print(f.__next__())  #输出f当前值
    print(f.__next__())
    print("休息一下")
    print(f.__next__())
    print(f.__next__())
    
    print("===从这里开始for循环==")
    for i in f:
        print(i)

    结果:

    <generator object fib at 0x03671230>
    1
    1
    休息一下
    2
    3
    ===从这里开始for循环==
    5
    8
    13
    21
    34
    55

      最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

     下面我们尝试通过生成器实现协程并行运算

    先来个前奏

    def consumer(name):
        print("%s 准备吃包子!" %name)
        while True:
            baozi=yield  #程序走到yield然后返回
            print("包子[%s]来了,被[%s]吃了!"%(baozi,name))
    
    c=consumer("Cherry")
    c.__next__() #调用生成器
    c.__next__()
    
    结果:
    Cherry 准备吃包子!
    包子[None]来了,被[Cherry]吃了! #因为没有包子,所以显示none

    因此,我们给做个包子

    def consumer(name):
        print("%s 准备吃包子!" %name)
        while True:
            baozi=yield  #yield作用是保持当前状态然后返回,直到下次执行时从这里继续执行
            print("包子[%s]来了,被[%s]吃了!"%(baozi,name))
    
    c=consumer("Cherry")
    c.__next__() #调用生成器
    baozi1="荠菜猪肉馅"
    a.send(baozi1) #send给yield赋值,然后yield传值给baozi
    
    结果:
    Cherry 准备吃包子!
    包子[荠菜猪肉馅]来了,被[Cherry]吃了!

    完整的正餐!

    #_*_coding:utf-8_*_
    
    import time
    def consumer(name):
        print("%s 准备吃包子!" %name)
        while True:
            baozi=yield
            print("包子[%s]来了,被[%s]吃了!"%(baozi,name))
    
    
    def producer(name):
        c=consumer('A')     #c是name为A的一个生成器
        c2=consumer('B')    #c2是name为A的一个生成器
        c.__next__()        #执行c的第一步操作
        c2.__next__()       #执行c2的第一步操作
        print("开始做包子!")
        for i in range(3):
            time.sleep(2)
            print("做了两个包子")
            c.send(i)       #执行c的下一步操作,把i传值给yield 
            c2.send(i)
    
    producer("Cherry")
    
    
    
    结果:
    A 准备吃包子!
    B 准备吃包子!
    开始做包子!
    做了两个包子
    包子[0]来了,被[A]吃了!
    包子[0]来了,被[B]吃了!
    做了两个包子
    包子[1]来了,被[A]吃了!
    包子[1]来了,被[B]吃了!
    做了两个包子
    包子[2]来了,被[A]吃了!
    包子[2]来了,被[B]吃了!
    完整版

     

  • 相关阅读:
    HDU 1162 Eddy's picture (最小生成树)(java版)
    codeforces 735D Taxes(数论)
    codeforces 735C Tennis Championship(贪心+递推)
    codeforces 2B The least round way(DP+数学)
    codeforces 2A Winner (好好学习英语)
    codeforces 632C The Smallest String Concatenation
    codeforces 803D Magazine Ad(二分+贪心)
    codeforces 803C Maximal GCD(GCD数学)
    codeforces 803B Distances to Zero
    STL容器之优先队列(转)
  • 原文地址:https://www.cnblogs.com/cherrycui/p/10272035.html
Copyright © 2020-2023  润新知