生成器

1.创建生成器

  • 方法1:
In [7]: nums = (x*2 for x in range(10))

In [8]: nums
Out[8]: <generator object <genexpr> at 0x7fb2a6137fc0>
In [9]: for num in nums:
   ...:     print(num)
   ...:
0
2
4
6
8
10
12
14
16
18
  • 方法2:
定义一个函数,让这个函数变成生成器
如果在调用函数的时候,发现这个函数中有yeild
那么此时,也就不是调用函数了,而是创建了一个生成器对象
def creat_num(all_num):
    print('~~~~~~~~~~~1~~~~~~~~~~~~~~~~~')
    a,b=0,1
    current_num  = 0
    while current_num < all_num:
        print('~~~~~~~~~2~~~~~~~~~~~~~~~~~')
        yield a # 相当于暂停了程序
        #print(a)
        print('~~~~~~~~~~~~~~3~~~~~~~~~~~~')
        a,b = b,b+a
        current_num += 1
        print('~~~~~~~~~~~4~~~~~~~~~~~~~~~~')

obj = creat_num(5)
# 一直next,发现程序会报错(告诉我们,生成器里面没有东西了),用try-except捕获并处理
while True:
    try:
        ret = next(obj)
        print('obj:',ret)
    except Exception as red:
        print(red.value)
        break

在这里插入图片描述
从图中我们可以看出执行到yield时,停下了,next则又继续例

  • 两个生成器对象之前并没有任何关系
obj = creat_num(5)
print(obj)
ret = next(obj)
print(ret)
ret = next(obj)
print(ret)
obj2 = creat_num(10)
print(obj2)
ret4 = next(obj2)
print(ret4)

在这里插入图片描述
从上图可以看出,obj和obj2之间没有任何关系,obj已经输出1了,这时再创个obj2,它输出的是0,从头开始,并不会接着obj的,所以没有任何关系

2. 生成器之send

  • 使用send唤醒程序

使用send()函数来唤醒程序执行,
使用send()函数的好处是:
可以在唤醒的同时向断点中传入一个附加的数据
def create_num(all_num):
    a, b = 0, 1
    current_num = 0
    while current_num < all_num:
        ret = yield a
        print('>>>>>>>>ret>>>>>>>', ret)
        a, b = b, a + b
        current_num += 1


obj = create_num(100)
red = obj.send(None)
print(red)
red = obj.send(None)
print(red)
red = obj.send(None)
print(red)

在这里插入图片描述

next和send得到的都是yield后面的值
不同的是send传递值而next不传递值

注意:
不能把send放在第一个,因为第一次执行程序是从开始执行
并没有值来接收send
如果你非要把send放在第一个,那么传递的值应该是None

生成器的应用

1. 实现多任务
import time
def task1():
    print('-----------')
    while True:
        print('-----1-----')
        time.sleep(0.1)
        yield
def task2():
    while True:
        print('-----2-----')
        time.sleep(0.1)
        yield
if __name__ == '__main__':
    i=0;
    t1=task1()
    t2=task2()
    while i<10:
        next(t1)
        next(t2)
        i+=1
    """
    类似于两个while True一起执行
    t1=task1()并不会进入task1内部,只是生成了生成器,所以没执行next之前不会输出任何东西
    先让t1执行,当t1遇到yield的时候,返回到next(t1),执行next(t2)
    执行t2时,遇到yield的时候,返回到next(t2)
    然后继续while循环
    这样t1/t2/t1/t2的交替运行,最终实现了多任务---->协程
    """

在这里插入图片描述

2. yield实现单线程并发
"""
 yield实现单线程并发
"""
import time

def consumer(name):
    print('%s 准备学习了~' %(name))
    while True:
        lesson = yield
        print('开始[%s]了,[%s]老师来讲课了~' %(lesson,name))

def producer(name):
    c1 = consumer('A')
    c2 = consumer('B')
    c1.__next__()
    c2.__next__()
    print('同学们开始上课了~')
    for i in range(10):
        time.sleep(1)
        print('到了两个同学')
        c1.send(i)
        c2.send(i)

producer('westos')
"""
利用了关键字yield一次性返回一个结果,阻塞,重新开始
send 唤醒
唤醒之后是从yield的下一行开始执行
"""

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值