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的下一行开始执行
"""