生成器

发布时间 2023-12-14 19:29:29作者: 苏苏!!

生成器

(一)什么是生成器

  • Python中的生成器是一种特殊的迭代器,可以在需要时生成数据,而不必提前从内存中生成并存储整个数据集。
  • 通过生成器,可以逐个生成序列中的元素,而无需一次性生成整个序列。
  • 生成器在处理大数据集时,具有节省内存、提高效率的特点。
  • 生成器是一种特特殊迭代器。
    • 迭代器不一定是生成器
    • 生成器一定是迭代器
"""生成器"""
#生成器:是一种特殊的迭代器
#迭代器不一定是生成器
#生成器一定是迭代器

(二)生成器创建方式

(1)列表推导式

  • 使用列表推导式时,可以将列表推导式的方括号改为圆括号,即可创建一个生成器。



#1.列表生成式生成列表
list=[ i  for i in  range(5)]
print(list)#[0, 1, 2, 3, 4]
#2.将列表改成元组
#看起来是一个元组,其实是一个生成器对象
tuple=(i  for  i  in  range(5))
print(tuple)#<generator object <genexpr> at 0x000001B4913044A0>

#用next()打印出生成器的每一个元素
print(next(tuple))
print(next(tuple))
print(next(tuple))
print(next(tuple))
print(next(tuple))
# 0
# 1
# 2
# 3
# 4



#生成器本身就是一个迭代器,可以用for循环遍历生成器对象
tuple=(i  for  i  in  range(5))
for i in tuple:
    print(i)
    
# 0
# 1
# 2
# 3
# 4

(2)yield关键字

  • yield关键字介绍
    • 使用yield关键字定义一个生成器函数时,生成器函数中的yield语句会暂停函数执行并返回一个值,下一次调用该函数时会继续执行并返回下一个值。
"""yield关键字"""
# my_generator()是一个生成器函数,通过yield关键字来逐个生成值
# 调用函数时,会得到一个生成器对象
# 可以用next()逐个的返回生成器中的值。
def my_generator():
    yield 1
    yield 2
    yield 3

my_generator=my_generator()
print(next(my_generator))
print(next(my_generator))
print(next(my_generator))
# 1
# 2
# 3
  • send方法 只能传一个位置参数,如果下传多个,可以考虑可变数据类型: 列表/字典/元组/集合。
# # send方法 只能传一个位置参数,如果下传多个,可以考虑可变数据类型:  列表/字典/元组/集合

# def eater():
#     print('开始吃饭 ovo ')
#     while True:
#         yield '开始喽'  # 第一次 next 发现有一个 yield ,卡住了
#         kwargs = yield  # 第二次 next 发现有一个 yield ,卡住了
#         print(f'得到的食物是 :>>>> {kwargs},  开始吃饭喽 :>>>> {kwargs}')
#
# my_eat = eater()
# print(next(my_eat), type(next(my_eat)))#开始喽 <class 'NoneType'>
# print(next(my_eat))# 得到的食物是 :>>>> None,  开始吃饭喽 :>>>> None   开始喽
# print(next(my_eat))#None
# print(next(my_eat))#得到的食物是 :>>>> None,  开始吃饭喽 :>>>> None   开始喽


# send方法传入一个参数
# def eater():
#     print('开始吃饭 ovo ')
#     while True:
#         yield '开始喽'  # 第一次 next 发现有一个 yield ,卡住了
#         kwargs = yield  # 第二次 next 发现有一个 yield ,卡住了
#         print(f'得到的食物是 :>>>> {kwargs},  开始吃饭喽 :>>>> {kwargs}')
#
# my_eat = eater()
# print(next(my_eat), type(next(my_eat)))#开始吃饭 ovo     开始喽 <class 'NoneType'>
# print(my_eat.send('麻辣香锅!'))#得到的食物是 :>>>> 麻辣香锅!,  开始吃饭喽 :>>>> 麻辣香锅! 开始喽
# print(next(my_eat))#None
# print(next(my_eat))#得到的食物是 :>>>> None,  开始吃饭喽 :>>>> None   开始喽
# print(next(my_eat))#None


# # send方法传入多个参数
# def eater():
#     print('开始吃饭 ovo ')
#     while True:
#         yield '开始喽'  # 第一次 next 发现有一个 yield ,卡住了
#         kwargs = yield  # 第二次 next 发现有一个 yield ,卡住了
#         print(f'得到的食物是 :>>>> {kwargs["food"]},  {kwargs["name"]}开始吃饭喽 :>>>> {kwargs["food"]}')
#
# my_eat=eater()
# print(next(my_eat))#开始吃饭 ovo     开始喽 <class 'NoneType'>
# print(next(my_eat))#None
# print(my_eat.send({'food':'酸菜鱼','name':'syh'}))#得到的食物是 :>>>> 酸菜鱼,  syh开始吃饭喽 :>>>> 酸菜鱼  开始喽
# print(next(my_eat))#none
  • 定义生成器并使用装饰器
# # 定义生成器  并使用装饰器
# def outer(func):# func -----eater生成器函数
#     def inner(*args,**kwargs):
#         my_eat=func(*args,**kwargs)# my_eat 是得到生成器对象
#         next(my_eat)#开始吃饭ovo
#         return my_eat
#     return inner
# @outer
# def eater(*args,**kwargs):
#     print('开始吃饭 ovo ')
#     while True:
#         kwargs = yield  # 第二次 next 发现有一个 yield ,卡住了
#         print(f'得到的食物是 :>>>> {kwargs}, {kwargs} 开始吃饭喽 :>>>> {kwargs}')
# 
# res=eater()
# print(res)
# res.send('酸菜鱼')#得到的食物是 :>>>> 酸菜鱼, 酸菜鱼 开始吃饭喽 :>>>> 酸菜鱼

生成器实现for循环

# 生成器实现for循环
def my_range(start,end,step=2):
    if start>end:
        print(f"开始值不能大于结束值")
    while start<end:
        yield start
        start+=step
myrange=my_range(start=0,end=10,step=2)
print(next(myrange))
print(next(myrange))
print(next(myrange))
print(next(myrange))
print(next(myrange))
# 0
# 2
# 4
# 6
# 8