生成器的作用
在我们需要创建一个庞大的数据,比如说100万个元素的列表,它会占用很大的存储空间。并且如果我们只需要访问前面的一些元素,那么后面的绝大多数元素所占用的空间都会浪费掉的。
而生成器generator是一种可以边循环边计算出后续所取值的机制。
使用生成器保存数据,不必创建所有的数据在里面,只有在取值的时候,它才会去通过某种算法去计算出要取的值,这样的话,就只有取值时,这个值才会占用空间,在该值不被使用后,则会被垃圾回收。
创建生成器的方式
1.把列表推导式外面的[]改成()即可:a = (x for x in range(5))
2.在函数定义中包含yield关键字,该函数就变成了生成器,并且还可以用来写伪并发函数:yield 返回值
生成器的取值方式
1.next(生成器变量):next(a)
2.生成器变量.send(值),有两个注意事项
2.1.在使用send()之前,需要先使用了next()
2.2.如果没使用next(),则第一次需要传空值:send.(None),否则会报错TypeError: can’t send non-None value to a just-started generator
例子(建议看注释)
例子1
generator_a = (x for x in range(5)) # 此时0-5这6个数字已经存在了内存中
print(generator_a) # <generator object at 0x000000000241CCA8>
print(next(generator_a)) # 0
print(next(generator_a)) # 1 此时0已经垃圾回收
print(next(generator_a)) # 2 此时1已经垃圾回收
例子2
def generator(): # 这类函数和其它函数的区别就是。执行了yield语句后就中断,下一个next 或send进来,则从中断处继续
print(‘one’)
yield 1 # 生成生成器并返回该值;中断
print(‘two’) # 第二次next或send,从这里开始运行
yield 2generator_b = generator() # 生成生成器对象
print(generator_b) # <generator object generater at 0x00000000021FCCA8>
print(next(generator_b)) # one 1
print(next(generator_b)) # two 2 此时上面的 one 1已经垃圾处理
例子3
def gen(max):
n, a, b = 0, 0, 1
while n < max:
count = yield a # 1.fib.send(None)执行到这,a=0返回去,暂停;2.a=1返回去,并暂停
print(count) # 2.fib.send(5)开始执行这里,输出5,然后执行下去
a, b = b, a + b # 2.a=1
n = n + 1gen = gen(5)
print(gen) # <generator object generater at 0x00000000021FCCA8>
print(gen.send(’’)) # generator.send(xxx):给该生成器赋值;但是第一次调用时,要么之前用了next(generator);要么就是传None:generator.send(None)
print(gen.send(None)) # 0
print(gen.send(5)) # 5 1 此时已经把a值赋给了count这个变量。并且获取了生成器的第二个值
例子4
‘’’
杨辉三角定义如下:
1
/
1 1
/ \ /
1 2 1
/ \ / \ /
1 3 3 1
/ \ / \ / \ /
1 4 6 4 1
/ \ / \ / \ / \ /
1 5 10 10 5 1
把每一行看做一个list,写一个generator,不断输出list:
‘’’
def triangles(n):
‘’’
分析:
N行的list的值,等于N-1行的list左右加0后的值相加,比如:
[1,3,3,1] = [0,1,2,1] + [1, 2, 2, 0]
这时候就可以使用zip()函数,来让后面的N-1行进行相加
zip()函数: 用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,
然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。
我们可以使用 list() 转换来输出列表。
'''
li = [1]
i = 0
while i < n:
yield li
# zip([0] + li, li + [0]):是为了生成左右两边多个[0]元素的list,元组形式返回
# sum(x):为了把这两个list的元素一一对应相加
li = [sum(x) for x in zip([0] + li, li + [0])]
i += 1
if name == ‘main’:
res = triangles(5)
for i in res:
print(i)