生成器是迭代器的一种形式
创建方式
- 表达式方式
>>> l = (i for i in range(10))
>>> l
<generator object <genexpr> at 0x109fbe6d0>
>>>
- 函数体 yield语句
生成器函数,但函数中有yield存在时,这个函数就是生产生成器函数。
def func():
print(111)
yield 1
print(222)
yield 2
print(333)
yield 3
print(444)
执行生成器函数时,会返回一个生成器对象。
注意,函数内部代码不会执行。
python
def func():
print(111)
yield 1
print(222)
yield 2
print(333)
yield 3
print(444)
data = func() # 创建生成器对象
# next(data) 可以调用生成器对象,生成器对象会运行函数内部语句,直到遇到yeild语句。并且可以通过赋值,接收yeild的值(这里类似return)
v1 = next(data)
print(v1)
v2 = next(data)
print(v2)
v3 = next(data)
print(v3)
v4 = next(data)
print(v4) # 结束或中途遇到return,程序爆:StopIteration 错误
next(data) 可以调用生成器对象,生成器对象会运行函数内部语句,直到遇到yeild语句。并且可以通过赋值,接收yeild的值(这里类似return)
def g():
print(1)
print(2)
yield 12
print(3)
print(4)
yield 34
print(5)
gen = g()
print(gen)
r1 = next(gen)
print(r1)
# 1
# 2
# 12
r2 = next(gen)
print(r2)
# 3
# 4
# 34
r3 = next(gen)
print(r3)
# 5
实际应用中,for循环可以代替手动一次次写next(gen),并且会自动处理收尾
for item in gen:
# next(gen)
print(item)
小结
- 创建方式
- 列表表达式
- 生成器函数(yield关键字)
- 特点
- yield 有返回值(类似return,可以进行赋值操作),但是相比return不是结束函数,而是暂停函数。
- 使用next(生成器),可以手动调用生成器,当遍历到超出返回时,会抛出——StopIteration 异常
- 可以使用for循环对生成器遍历
生成器应用
-
节省内存空间 :当遇到需要创建大量数据时,可以使用生成器,用多少,取多少。
import random
def get_random_number(max_count):
"""
生成 max_count 个随机4位数
"""
count = 0
while count < max_count:
yield random.randint(1000, 9999)
count += 1
data_list = get_random_number(3000000)
扩展
通过send方法跟参数,可以给yield传值,在生成器内部需要对yield传值
def func():
print(111)
v1 = yield 1
print(v1)
print(222)
v2 = yield 2
print(v2)
print(333)
v3 = yield 3
print(v3)
print(444)
data = func()
n1 = data.send(None)
print(n1)
n2 = data.send(666)
print(n2)
n3 = data.send(777)
print(n3)
n4 = data.send(888)
print(n4)