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: #用for循环取生成器
...: print(num)
...:
0
2
4
6
8
10
12
14
16
18
2.创建生成器的方法2(定义一个函数,让这个函数变成生成器)
之前我们写过斐波那契数列:
# 1 1 2 3 5 8 13...
# def fib(num):
# a,b,count = 0,1,1
# while count <= num:
# print(b)
# a,b = b,a+b
# count +=1
#
# fib(1000)
那么生成器对象是什么呢?
如果在调用函数的时候,发现这个函数中有yeild,那么此时,也就不是调用函数了,而是创建了一个生成器对象。
def creat_num(all_num):
print('~~~~~~~~~~~1~~~~~~~~~~~~~~~~~')
#利用print来看程序运行到哪一步暂停
a,b=0,1
current_num = 0
while current_num < all_num:
print('~~~~~~~~~2~~~~~~~~~~~~~~~~~')
yield a # 相当于暂停了程序,并输出a
print('~~~~~~~~~~~~~~3~~~~~~~~~~~~')
a,b = b,b+a
current_num += 1
print('~~~~~~~~~~~4~~~~~~~~~~~~~~~~')
obj = creat_num(5)
print(obj)
可以看出生成的 creat_num为以一个生成器对象。
为了学习yield工作原理,利用next()函数继续输出。发现到yield暂停,并且输出了a
obj = creat_num(5)
print(obj)
ret = next(obj)
print(ret)
再继续利用next()观察下一步,也是运行到yield停止
obj = creat_num(5)
print(obj)
ret = next(obj)
print(ret)
ret1 = next(obj)
print(ret1)
接着运行,因为all_num=5,但是next()可以一直循环,发现当运行第六次时报错。
obj = creat_num(5)
print(obj)
ret = next(obj)
print(ret)
ret1 = next(obj)
print(ret1)
ret2 = next(obj)
print(ret2)
ret3 = next(obj)
print(ret3)
ret4 = next(obj)
print(ret4)
ret5 = next(obj)
print(ret5)
#此时.我们发现程序会报错(告诉我们,生成器里面没有东西了)
在一次无限循环中,如何知道哪一步函数报错呢?
这需要异常补货预警:except Exception as red(任意名)
obj = creat_num(5)
while True:
try:
ret = next(obj)
print('obj:',ret)
# 异常补货预警except Exception as red(任意名):
except Exception as red:
print(red.value)
# 可以输出你想返回的值例如:print('111')
break
#输出生成器的值
obj = creat_num(5)
for num in obj:
print(num)
注意:两个生成器对象之前并没有任何关系
obj2 = creat_num(100) #取新的生成器obj2
print(obj2)
ret4 = next(obj2) #仍然是运行重新开始,从运行结果可以看出,yield返回的值是0
print(ret4)
3.使用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 = next(obj)
print(red)
red = obj.send('hello') #将hello传递给端点处
print(red)
next和send得到的都是yield后面的值
不同的是send传递值而next不传递值
注意:
不能把send放在第一个,因为第一次执行程序是从开始执行
并没有值来接收send
如果你非要把send放在第一个,那么传递的值应该是None
把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 = next(obj)
# print(red)
red = obj.send('hello') #把send放在第一个时,程序报错
print(red)
把send放在第一个并且传递值为none时:
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 = next(obj)
# print(red)
red = obj.send(None) #传递值为None
print(red)
输出第一个值为0