python生成器学习笔记
为什么要有生成器?
生成器不会把所有数据一次性加载到内存中,而是在每次循环时临时生成一个数据,这样每次循环的过程中内存中只会出现一个数据,防止内存溢出
获取一个生成器
num_gen = (i for i in range(1,100000000))
#num_gen是一个生成器
print(type(num_gen))
for i in num_gen:
#遍历
print(i)
自定义一个生成器
类似于自定义函数,但里面含有关键字yield,使用next()函数可以让生成器中的代码执行,直到遇到yield则会返回一次结果,并且将该函数冻结(意味着将保留生成器内所有局部变量的值),直到遇到下一个next().
另外使用return会抛出StopIteration异常,因此生成器中应尽量避免使用return
def test_gen1():
yield 'a'
yield 'b'
yield 'c'
gen1 = test_gen1()
#此时会返回一个生成器
print(next(gen1))
print(next(gen1))
print(next(gen1))
#分别打印出了'a','b','c'
next(gen1)
#此时会抛出异常StopIteration
使用生成器遍历1到1亿
def test_gen2(start,end):
index = start
while index <= end:
yield index
index +=1
#gen2既是生成器也是可迭代对象、迭代器,因此可以使用for循环进行遍历,并且只能被遍历一次
gen2 = test_gen2(1,100000000)
for i in gen2:
print(i)
send()方法
send()方法,与next()类似,但是还可以给yield表达式传值,对于第一次执行生成器,send只能传None,否则会报错
def test_gen3(start):
while start < 10:
#如果使用next()执行,咋yield start表达式返回的值永远是None
temp = yield start
print(temp)
start += 1
gen3 =test_gen3(1)
print(next(gen3))
#打印1
print(next(gen3))
#打印None和2
print(gen3.send('hello world'))
#打印hello world和3
生成器案例:打印斐波那契数列
def feb(end):
#打印前end位
count = 0
a,b = 0,1
while count < end:
yield b
temp = b
b = a + b
a = temp
count += 1
for i in feb(9):
print(i)