生成器

发布时间 2023-12-15 09:04:35作者: ssrheart

生成器

  • 生成器一定是迭代器,迭代器不一定是生成器
    • 可以在需要时生成数据,通过生成器,可以逐个生成序列中的元素,而无需一次性生成整个序列
  • 生成器也能用next()方法,因为生成器是一种特殊的迭代器

【一】生成器的两种创建方式

(1)列表生成式

  • 列表
num_list = [i for i in range(10)]
print(num_list)

(2)元组生成式

  • 查看元组生成式里面的数据:用list类型强转成列表
num_tuple = (i ** 2 for i in range(10))
print(num_tuple, type(num_tuple))  # <generator object <genexpr> at 0x000002CCAA794350> <class 'generator'>
print(list(num_tuple))  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

【二】yield关键字

(1)yield关键字介绍

  • 使用yield关键字定义一个生成器函数时,生成器函数中的yield语句会暂停函数执行并返回一个值,下一次调用时会继续执行并返回下一个值
def my_generator():
    yield 1
    yield 2
    yield 3

my_iter = my_generator()
print(next(my_iter))
print(next(my_iter))
print(next(my_iter))

(2)yield关键字使用

  • 向yield传值的前提是,必须卡在使用这个值的前面的yield上面
def eat():
    print('开始吃饭')
    while True:
        food = yield
        print(f'得到的食物是 :>>>{food},开始吃饭:>>> {food}')

my_eat=eat()
print(next(my_eat))
print(my_eat.send('宫保鸡丁')) 
# 开始吃饭
# None
# 得到的食物是 :>>>宫保鸡丁,开始吃饭:>>> 宫保鸡丁
# None
  • send方法只能传一个位置参数,不能传两个,如果想传多个,可以考虑可变数据类型:字典/列表/元组/集合
def wrapper(func):  # eater 生成器函数
    def inner(*args, **kwargs):
        my_eat = func(*args, **kwargs)  # my_eat得到的是生成器对象
        # print(my_eat)  # <generator object eater at 0x000001DA9FB668F0>
        next(my_eat)  # 开始吃饭 ovo
        return my_eat

    return inner

@wrapper  # eater = wrapper(eater)
def eater():
    print('开始吃饭 ovo ')
    while True:
        kwargs = yield  # 第二次 next 发现有一个 yield ,卡住了
        print(f'得到的食物是 :>>>> {kwargs["food"]}, {kwargs["name"]} 开始吃饭喽 :>>>> {kwargs["food"]}')


res = eater()
res.send({'food': '茄子肉丁', 'name': 'hope'})
res.send({'food': '拔丝红薯', 'name': 'dream'})

(3)生成器实现for循环

def my_range_one(start, end, step=1):
    if end < start:
        print(f'开始值不能大于结束值')
    while start < end:
        yield start
        start += step


for i in my_range_one(start=1, end=10, step=1):
    print(i)