python中生成器

 一个函数使用了yield就变成了一个生成器(generator),跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器

def test1():
    aa = 'hi'
    while True:
        yield aa
        print('i am aa')

def test2():
    bb = 'hello'
    while True:
        yield bb
        print('i am bb')

if __name__ == '__main__':
    aa = test1()
    print(next(aa))  # 返回aa并中断test1函数
    print(next(aa))  # 从test1函数中断处执行,执行print,然后返回aa并中断test1函数
    bb = test2()
    print(bb.__next__())  # 也可以用__next__方法

运行结果:

hi
i am aa
hi
hello

原理:在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值。并在下一次执行 next()方法时从当前位置继续运行 如果遇到yield 语句,会挂起函数的运行状态,并将yield 右边的表达式的值返回给next()的调用者, 挂起的时候会保存所有本地状态,包括局部变量,指令指针和内部堆栈信息,这样当下次再次调用next()时, 看起来yield 部分就像是调用了一个外部调用一样,可以接着往下执行

通过原理我们了解,生产器是调用一次执行一次,应用在大量计算的函数中,对内存是较友好的,比如经典的斐波那契数列

def fib(n):
    a = b = 1
    for i in range(n):
        yield a
        a, b = b, a + b

生产器还提供了send()方法来进行生成器间的互动,PS第一次调用时需要注意下

before you can communicate with a coroutine you must first call next() or send(None) to advance its execution to the first yield expression.

def test1():
    aa = 'hi'
    while True:
        cc = yield aa
        yield cc

if __name__ == '__main__':
    t = test1()
    t.send(None)  #启动
    print(next(test1()))  #遇到第一个yield返回,aa值'hi'
    print(t.send('hello'))  #cc被赋值'hello',yield cc返回'hello'

运行结果:

hi
hello

有了互动方法,来实现下生产者消费者

def consumer():
    c = '消费者'
    while True:
        r = yield c
        if not r:
            return
        print('开始消费{}'.format(r))
        c = f'消费{r}完成'

def produce(c):
    print(c.send(None))
    for i in range(1,6):
        print('开始生产{}'.format(i))
        r = c.send(i)
        print('消费者,{}'.format(r))
    c.close()

if __name__ == '__main__':
    c = consumer()
    produce(c)

运行结果:

消费者
开始生产1
开始消费1
消费者,消费1完成
开始生产2
开始消费2
消费者,消费2完成
开始生产3
开始消费3
消费者,消费3完成
开始生产4
开始消费4
消费者,消费4完成
开始生产5
开始消费5
消费者,消费5完成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值