python -生成器

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
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43067754/article/details/84847634