zoukankan      html  css  js  c++  java
  • Python函数(十一)-生成器

    首先看一下什么是列表生成式

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

    这一句代码就实现了三句代码的效果,这一句代码就是列表生成式

    列表如果存的数据太多,就会占用很大的存储空间

    如果只取列表中的一些数据,那么其它不用的数据占用的存储空间就白占了

    生成器也能存储数据,但是它只记录当前数据,剩下的数据都还没生成,这样就不会占用太多的存储空间

    怎么创建一个生成器呢?

    >>> [i*2 for i in range(10)]
    [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
    >>> (i*2 for i in range(10))
    <generator object <genexpr> at 0x0000021C9C2E5258>
    

    这样就是一个生成器了,没有直接生成数据

    要取一个数据就生成一个数据

    那么怎么获取生成器里的数据呢?

    >>> b = (i*2 for i in range(10))
    >>> b
    <generator object <genexpr> at 0x0000021C9C2E5308>
    >>> b.__next__()
    0
    >>> b.__next__()
    2
    >>> b.__next__()
    4
    >>> next(b)
    6
    >>> next(b)
    8
    >>> next(b)
    10
    

    生成器使用next()方法获取数据,next(b),这是Python3和Python2通用的方法

    Python3中还可以用__next__()方法,b.__next__()

    Python2中用next()方法,b.next()

    但是用next()方法一次次取数据太麻烦,所以通常都用for循环来打印数据

    >>> c = (i*2 for i in range(10))
    >>> for n in c:
    ...     print(n)
    ...
    0
    2
    4
    6
    8
    10
    12
    14
    16
    18
    

    如果函数里有yield关键字,这个函数就是生成器

    # -*- coding:utf-8 -*-
    __author__ = "MuT6 Sch01aR"
    
    def test(n):
        m = 0
        b = 0
        while m<n:
            print("before yield")
            yield b
            b = b+3
            print("after yield")
            m =m+1
        return "test return"
    
    a =test(10)
    
    while True:
        try:
            b = a.__next__()
            print("in the next",b)
        except StopIteration as e:
            print(e.value) #StopIteration的value为生成器的返回值
            exit()
    

    运行结果

    运行过程:

    首先是调用test()函数

    然后执行while循环

    到__next__()方法的时候,跳到test()函数

    执行完yield后,没继续执行下面的语句,而是返回到__next__()方法后的语句

    执行完该语句后继续执行while循环,执行__next__()方法

    然后又跳转到yield后的语句

    生成器调用next()方法的时候执行,执行到生成器中的yield的时候返回,然后执行next()方法后的语句,再执行到next()方法的时候,就会跳到执行yield的语句,之后执行yield后的语句

    用生成器实现单线程多并发

    # -*- coding:utf-8 -*-
    __author__ = "MuT6 Sch01aR"
    
    import time
    
    def consumer(name):
        print('%s准备吃包子' %name)
        while True:
            baozi = yield
            print('%s包子来了,被%s吃了' %(baozi,name))
    
    def producer():
        c = consumer('张三')
        c2 = consumer('李四')
        c.__next__()
        c2.__next__()
        print('我开始准备做包子了')
        for i in range(10):
            time.sleep(1)
            print('我做了2个包子')
            c.send('肉') #调用yield,并传值
            c2.send('菜')
    
    if __name__ == '__main__':
        producer()
    

    send方法不仅可以调用yield,还给yield传值

    运行结果

    实现了单线程多并发的效果

  • 相关阅读:
    202104-2 邻域均值
    202104-1 灰度直方图
    1384. 饲料调配
    1381. 阶乘
    264. 丑数 II
    1380. 邮票
    42 新安装的idea必备设置
    41 cmd中解除被占用的端口
    40 文件在线预览
    39 进度条使用
  • 原文地址:https://www.cnblogs.com/sch01ar/p/8410599.html
Copyright © 2011-2022 走看看