生成器

发布时间 2023-12-13 21:47:41作者: 桃源氏

生成器

  • 在python中,生成器是一种特殊的迭代器,可以在需要时生成数据,不必从内存中生成并存储整个数据集

一、创建方式

[1]列表推导式 :生成列表

  • 使用列表推导式时,只要将列表推导式的方括号改成圆括号,就可以创建一个生成器
list_num = [i for i in range(5)]
print(list_num)  # [0, 1, 2, 3, 4]

#将列表推导式的方括号改成圆括号,就创建了一个生成器
gtr = (i for i in range(5))
print(gtr)  # <generator object <genexpr> at 0x000001DD1C7B82E0>

#生成器无法直接打印,需要进行强转
print(list(gtr))  # [0, 1, 2, 3, 4]
  • 如果我们想将生成器中的东西打印出来,可以使用_next_方法打印出来
  • 缺点是只能一个一个的打印,所以使用for循环,进行迭代它,因为生成器也是一个可迭代对象
gtr = (i for i in range(5))
for i in gtr:
    print(i, end='  ')  # 0  1  2  3  4

[2]yield关键字

  • 使用yield关键字定义一个生成器函数时,生成器函数中的yield语句会暂停函数执行并返回一个值,下一次调用该函数时会继续执行并返回下一个值。
def add():
    yield "这是第一步!"
    yield "这是第二步!"
    yield "这是第三步!"


gtr = add()
print(next(gtr))
print(next(gtr))
print(next(gtr))

'''
这是第一步!
这是第二步!
这是第三步!
'''
  • 还可以使用yield关键字和send()方法进行代码的传值。
def shop():
    print("开始购物!")
    while True:
        goods = yield
        print(f"购买了{goods}")


shopping = shop()

#当函数中是用来yield关键字后,函数就变成了一个生成器,需要next()方法来执行
next(shopping)  # 开始购物!
#当我们没有使用send()进行传值时,goods就没有值,打印出了None
next(shopping)  # 购买了None
#传入值后就正常打印
shopping.send("笔记本!")  # 购买了笔记本!

二、yield+next详解

def wrapper(func):
    def inner():
        gtr = func()
        next(gtr)
        return gtr

    return inner()


def shop():
    print("开始购物!")
    while True:
        yield
        print("选择商品!")
        goods = yield
        print(f"购买了{goods}")

#若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即生成器对象
#因为shop函数已经变成了生成器对象,所以使用修饰器执行了next之后就直接打印了第一句话,之后被yield拦下
shop = wrapper(shop)  # 开始购物!

#再次使用next进入下一行代码
next(shop)  # 选择商品!

#因为goods没有传值使用打印出来None
next(shop)  # 购买了None

#再次进入输入的时候
next(shop)  # 选择商品!

#传入了值,所以打印了值
shop.send("笔记本")  # 购买了笔记本
  • 这样就可以尝试使用生成器实现range的功能
def my_range(start, end, step=1):
    if end < start:
        print(f'开始值不能大于结束值!')
    while start < end:
        yield start
        start += step


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

[4]生成器的特点

  • 节约内存
  • 迭代到下一次的调用时,所使用的参数都是第一次所保留下的
  • 即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的