# 生成器generator:一边循环一边计算的机制 # 相对于列表推导式来说,不必创建完整的列表,能够节省大量的空间

目录

1.创建生成器

方式1.使用列表推导式得到生成器:

方式2:next(生成器对象) ---系统内置的函数

方式3:通过‘函数+ yield’产生生成器 

3.生成器方法send()

4.生成器应用--多任务

5.总结


 

1.创建生成器

方式1.使用列表推导式得到生成器:

# 方式1.使用列表推导式得到生成器:
# 只需要把列表推导式的[]换成(),就是生成器类型

# 例如:得到[0,10)中3的倍数的数值
res = (x*3 for x in range(10))
print(type(res))
# <class 'generator'>
print(res)
# <generator object <genexpr> at 0x000002B32733F620>

# 得到生成器里面的元素
print(res.__next__())
print(res.__next__())  # 每调用以此就生成一个元素
print(res.__next__())

方式2:next(生成器对象) ---系统内置的函数

# 方式2:next(生成器对象) ---系统内置的函数
# 每调用一次next(),就会产生一个元素
# PS:当让生成器产生元素过量的时候,会出现异常StopIteration
print(next(res))  # 9
print(next(res))  # 12
print(next(res))  # 15
print(next(res))  # 18

# 处理这种异常StopIteration
while True:
    try:
        e = next(res)
        print(e)
    except:
        print('没有更多元素了!')
        break
# 21
# 24
# 27
# 没有更多元素了!

方式3:通过‘函数+ yield’产生生成器 

'''
通过函数产生生成器
步骤:
1.定义一个函数,函数中使用yield关键字
2.调用函数,接收调用的结果
3.得到的结果就是生成器
4.借助于next(),__next__()得到元素
'''


# yield
# 只要函数中出现了yield关键字,函数就不是函数了,而是变成了生成器
def func():
    n = 0
    while True:
        n += 1
        yield n  # yield n 的作用相当于:return n + 暂停【暂停在该位置,下次再调用的时候从此位置开始】


g = func()
print(g)  # <generator object func at 0x00000189D61AF620>

print(next(g))    # 1

应用:斐波那契数列

# 斐波那契数列
def fib(length):
    a, b = 0, 1
    n = 0

    while n < length:
        yield b
        a, b = b, a+b
        n += 1

    return '没有更多元素了!!!'   # 返回错误信息


g = fib(6)
print(next(g))
print(next(g))
print(next(g))
# 1
# 1
# 2

3.生成器方法send()

# 生成器之方法send()
# 向每次调用生成器的时候传值,第一次调用需要传入None
def gen():
    i=0
    while i<5:
        temp = yield i
        print('temp:',temp)
        i+=1

    return '没有元素了'


g = gen()
# print(next(g))
# print(next(g))
# print(next(g))
# # 0
# # temp: None
# # 1
# # temp: None
# # 2

# g.send(None)
print(g.send(None))  # 第一次要用g.send(None)
n1 = g.send('mico')
print('n1:',n1)
n2 = g.send('xiaoha')
print('n2:',n2)
# 0
# temp: mico
# n1: 1
# temp: xiaoha
# n2: 2

4.生成器应用--多任务

# 进程>线程>协成
# 进程
# 线程
# 协程:线程的小分支

# 1.不加协程的时候-----------【全部做完菜,再做汤】----------------------
def task1(n):
    for i in range(n):
        print('正在做第{}个菜*****'.format(i))
        i += 1


def task2(n):
    for i in range(n):
        print('正在做第{}个汤-----'.format(i))
        i += 1


task1(3)
task2(3)
# 这样执行的结果为:【全部做完菜,再做汤】
# 正在做第0个菜*****
# 正在做第1个菜*****
# 正在做第2个菜*****
# 正在做第0个汤-----
# 正在做第1个汤-----
# 正在做第2个汤-----


# 2.加协程的时候----------【一边做菜,一边做汤】-----------------------
def task1(n):
    for i in range(n):
        print('正在做第{}个菜*****'.format(i))
        i += 1
        yield   # yield不加n的时候,只是用了其暂停功能,不抛出值


def task2(n):
    for i in range(n):
        print('正在做第{}个汤-----'.format(i))
        i += 1
        yield


g1 = task1(3)
g2 = task2(3)
while True:
    try:
        g1.__next__()
        g2.__next__()
    except:
        pass

# 运行结果为:【一边做菜,一边做汤】
# 正在做第0个菜*****
# 正在做第0个汤-----
# 正在做第1个菜*****
# 正在做第1个汤-----
# 正在做第2个菜*****
# 正在做第2个汤-----

5.总结

--创建生成器:
1.列表推导式
2.函数+yield

--产生元素:
1.next(generator)
2.生成器自己的方法:
   g.__next__()
   g.send(value)
   
--应用:协成

PS:部分内容参考千锋教育,如有侵权,请联系删除!谢谢!