生成器

作者: 戈羽殇雪 | 来源:发表于2019-11-06 18:24 被阅读0次

列表生成式,一般的我们想把对一个列表的函数进行操作,一般是用循环进行调用。
例如我们想将0-9的元素乘以2,一般来讲:

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

而我们使用列表生成式的话,直接可以写作

list=[ i*2 for i in range(10)]

直接打印即可,得到一个列表,这样简洁了很多,同时不需要循环引入
列表生成式,在面对大数据量的时候,不会直接占用那么大的内存,它
只是引入了一个算法,只有在调用到列表的这个元素时,它才会生成这个元素,若一个100w元素的列表,传统的调用方式,会首先分配部分内存给这100w个元素,但若使用列表生成式,只有开始调用时,才会占用内存空间。

而生成器简单来讲,就是将列表生成式外卖呢的[]转换成()

list=(i*2 for i in range(10)]
print(type(list))
output:
<class 'generator'>

生成器只有一种方法,就是next方法,调用方式为:

f=(i*i for i in range(5) )
print(f.__next__())
print(f.__next__())

生成器只能记录当前的位置,不计前后,没有上一个这种方法
如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现
实现斐波那契数列

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

这里需要注意的一点,最关键一点为a,b=b,a+b,
如果顺序执行的方式去执行

a=b
b=a+b

则循环输出结果为:1,2,3,6.....违背了数列的规律
实际上应该理解为:

t=(b,a+b)
a=t[0]
b=t[1]

输出为:1,1,2,3,5,8
而我们这里可以引入生成器,只需将print(b)修改为yield b

def fib(max):
    n,a,b =0,0,1
    while n < max:
        yield b
        a,b = b,a+b
        n = n+1
    return 'done'

同时调用时可以查看fib(6)的类型,可以看到为
<class 'generator'>
若要调用生成器还是需要使用next方法
print(f.next())
将6个值都取到则需要调用6次next方法
但当调用第7次时,程序会报错,抛出“StopIteration”的异常
因此我们可以改写调用函数:

def fib(max):
    n,a,b =0,0,1
    while n < max:
        yield b
        a,b = b,a+b
        n = n+1
    return 'done'
f=fib(10)
while True:
    try:
        x = next(f)
        print('f:',x)
    except StopIteration as e:
        print('Generator return value:',e.value)
        break

while 循环中的next函数实际作用与内置函数f.next()一致
通过异常判断来修正程序,不会出现报错的情况,同时中断程序

另外我们可以使用生成器来写一个简单的生产者消费者模型

def consumer(name):
    print("%s 准备吃包子了!" %name)
    while True:
        baozi=yield
        print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
c=consumer('carl')
c.__next__()
c.send("韭菜馅")

我们看到这里将生成器赋值给“baozi”,这里的生成器就是保存状态,next是唤醒这个生成器,而用send方法是给生成器传值,而consumer是消费者,吃包子的

next方法与send方法都可以调用生成器,但不同的是next方法是调用生成器的值,而send方法则是向生成器传值
而consumer是吃包子的,send值则代表生产包子

完整的做包子,吃包子模型:

import time

def consumer(name):
    print("%s 准备吃包子啦!" % name)
    while True:
        baozi = yield  ##将生成器赋值给包子
        print("包子[%s]来了,被[%s]吃了!" % (baozi, name))
c=consumer('cris')

def producer(name):
    c = consumer('A')
    c2 = consumer('B')
    c.__next__()
    c2.__next__()
    print("%s开始准备做包子啦!" %name)
    for i in range(1,10):
        time.sleep(1)
        print("做了%s个包子!" %i)
        c.send(i)
        c2.send(i)
producer("cris")

相关文章

  • 15.生成器generator

    目录:1.生成器介绍2.生成器举例3.生成器应用 1.生成器介绍 生成器指的是生成器对象,可以由生成器表达式得到,...

  • 2018-07-16

    ## 1\. 生成器和生成器函数 ``` 生成器的本质就是迭代器 生成器的三种创建办法: 1.通过生成器函数 ...

  • 第014篇:三大神器之生成器

    Python的三大神器:装饰器、迭代器、生成器 1、生成器 1.1、什么是生成器 生成器就是迭代器的一种;生成器作...

  • Python 生成器函数

    一、生成器 生成器指的是生成器对象,可由生成器表达式得到,也可使用 yield 关键字得到一个生成器函数,调用这个...

  • tornado协程的工作原理

    包含yield语句的函数是一个生成器。所有的生成器都是异步的。当我们调用生成器函数的时候,生成器函数返回一个生成器...

  • python 生成器小结

    作者:邵正将 来源:PytLab 在python中生成器可以很方便的实现迭代协议。生成器通过生成器函数产生,生成器...

  • ES6 Generators

    生成器函数 生成器函数以function*标注 yield关键字,会暂停生成器的执行,在之后可以继续执行 生成器的...

  • ES6 生成器Generator

    生成器 生成器(Generators): 一个更好的方法来构建遍历器。 --- 生成器和迭代器 生成器就是一类...

  • 生成器

    生成器指的是生成器对象,可以有生成器表达式获得,也可以由yield关键字得到一个生成器,调用这个函数得到一个生成器...

  • Python 入门之 Python三大器 之 生成器

    Python 入门之 Python三大器 之 生成器 1、生成器 (1)什么是生成器? 核心:生成器的本质就是一个...

网友评论

      本文标题:生成器

      本文链接:https://www.haomeiwen.com/subject/ypwdbctx.html