生成器(generator):
生成器的本质就是迭代器
创建生成器的两种方案:
1. 生成器函数
2. 生成器表达式
生成器函数
生成器函数中有一个关键字yield
生成器函数执行的时候, 并不会执行函数, 得到的是生成器.
yield: 只要函数中出现了yield. 它就是一个生成器函数
作用:
1. 可以返回数据
2. 可以分段的执行函数中的内容, 通过__next__()可以执行到下一个yield位置
优势:
用好了, 特别的节省内存
生成器表达式 -> 一次性的
语法: (数据 for循环 if)
正常的函数调用如下:
def func():
print(123456)
return 999
ret = func()
print(ret)
#运行结果
123456
999
使用生成器命令yield
替代return
。生成器函数执行的时候,并不会执行函数,得到的是生成器。
def func():
print(123456)
yield 999 # yield也有返回的意思.
ret = func()
print(ret)
#运行结果
<generator object func at 0x115f2dbd0>
生成器的本质就是迭代器,因此我们可以用迭代器的模式使用它:
def func():
print(123456)
yield 999 # yield也有返回的意思.
ret = func()
print(ret.__next__()) # yield只有执行到next的时候才会返回数据
#运行结果
123456
999
上面运行结果中:123456是函数的正常执行,999是yield
返回的值,也就是说999是print()
打印出来的,我们把print()
拿掉就可以看到只有123456了
def func():
print(123456)
yield 999 # yield也有返回的意思.
ret = func()
ret.__next__()
#运行结果
123456
因此我们可以发现,yield
和return
是有一些区别的:return
的用法是立即执行函数,并返回数据,而yield
是只有执行到next的时候,才会返回数据。
如果我们执行2次next()又会出现和迭代器一样的StopIteration
报错
def func():
print(123456)
yield 999 # yield也有返回的意思.
ret = func()
print(ret.__next__()) # yield只有执行到next的时候才会返回数据
print(ret.__next__()) # StopIteration
#运行结果
123456
999
Traceback (most recent call last):
File "D:\迭代器.py", line 8, in <module>
print(ret.__next__()) # StopIteration
^^^^^^^^^^^^^^
StopIteration
这也证明了:" 生成器的本质就是迭代器"
yield可以让程序分段的执行函数中的内容, 通过__next__()可以执行到下一个yield位置
执行一次:
def func():
print(123)
yield 666
print(456)
yield 999
ret = func()
print(ret.__next__())
#运行结果
123
666
执行两次:
def func():
print(123)
yield 666
print(456)
yield 999
ret = func()
print(ret.__next__())
print(ret.__next__())
#运行结果
123
666
456
999
这里yield
就明显区别与return
:当使用return
的时候(比如return 666
),return
后面的内容全部都不会再执行。
去工厂定制10000件衣服
def order():
lst = []
for i in range(10000):
lst.append(f"衣服{i}")
return lst
lst = order()
print(lst)
简单的for循环会一次性生产出10000件衣服,并且出现了大列表lst[0,1,2,3,……,9999]
这样会严重占用内存,并且双方都不好处理。
为此我们使用生成器玩法,让每次出货量为100件,每次执行__next__
后再生产100件,这样就非常不占用内存,并且生产压力和库存压力都减少很多。
def order():
lst = []
for i in range(10000):
lst.append(f"衣服{i}")
if len(lst) == 100:
yield lst
# 下一次拿数据
lst = [] #清空计数器重新计数
gen = order()
print(gen.__next__())
print(gen.__next__())
print(gen.__next__())
print(gen.__next__())
还可以用一个列表去接收这些yield的值:
def order():
lst = []
for i in range(10000):
lst.append(f"衣服{i}")
if len(lst) == 100:
yield lst
# 下一次拿数据
lst = [] # 清空计数器重新计数
gen = order()
# 用于追加结果的列表
result_list = []
# 逐次执行生成器并追加结果到列表中
result = next(gen)
result_list.append(result)
result = next(gen)
result_list.append(result)
result = next(gen)
result_list.append(result)
result = next(gen)
result_list.append(result)
# 打印包含所有结果的列表
print(result_list)
以下这段代码,存在的意义就是,使用生成器的yield特性,将程序分段执行,这样就可以避免庞大的数据执行时,严重占用内存的现象。
def order():
lst = []
for i in range(10000):
lst.append(f"衣服{i}")
if len(lst) == 100:
yield lst
# 下一次拿数据
lst = [] # 清空计数器重新计数
gen = order()
# 使用 list() 函数接收生成器的 yield 返回值
result_list = list(gen)
在处理大型数据集或者生成器产生的数据量很大时,一次性获取所有值可能会导致内存占用较大,因为所有值都需要同时存储在内存中。在这种情况下,你可能希望逐个获取生成器的值,以减小内存压力。
如果数据量较大或者你希望逐个获取生成器的值,那么逐次调用 next(gen)
会更有优势!
这就是生成器的存在的价值。
标签:__,generator,Python,生成器,yield,next,lst,print From: https://www.cnblogs.com/Magiclala/p/17865594.html