生成器
- 在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("笔记本") # 购买了笔记本
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]生成器的特点
- 节约内存
- 迭代到下一次的调用时,所使用的参数都是第一次所保留下的
- 即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的