先介绍生成器之前 先要了解为什么要有生成器,生成器的使用场景是什么。
列表生成式 变成生成器
如下:
a=[x*2 for x in range(1000000) if x%2==0 ]
print (a)
当列表很庞大的时候, 内存根本装不了,这个时候系统就崩掉。 这个时候要用生成器 。
生成器: 是指 它只会记忆你的计算过程,当你需要的时候随便取,不会一下子就全部给你。
如果把列表生成式变成 生成器对象呢 ?请看以下代码 :
a=(x*2 for x in range(1000000) if x%2==0 )
print(a)
很简单就是把 中括号变成 小括号, 打印的结果如下:
<generator object <genexpr> at 0x0000026A39E02A40>
一看就是个 生成器对象 ,那我们应该怎么取值呢 ?前面我们介绍了,生成器也是迭代器, 迭代器取值就可以用next()
如下:
a=(x*2 for x in range(1000000) if x%2==0 )
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
打印结果:
0
4
8
12
16
20
24
我们通过打印结果可以看出 ,他每次都要调用方法然后返回值停止,你再调用继续执行然后返回值提停止, 所以就是 记忆计算过程。
这就是 取出来一个值,交给其他程序处理, 处理完了 再取值 。
我再举一个 带有 yield 表示的生成器
看下这边的代码 如下:
def test():
print("----start-----")
a = 0
b = 1
for i in range(14):
print("-----1------")
yield b
a,b=b,a+b
print("--------2-----")
print("--------3---------")
test()
当我们执行test() 的时候是什么都打印不出来的, 小伙伴该想了我不是执行了吗 ,怎么不打印东西呢, 最起码把 start 打印出来呀。
解释如下:
- test() 执行以后返回的是生成器对象,大家记住只要带 yield 都是生成器,生成器对象 你不调用是不会取值的,他只是记忆下有这个过程
- 取值要用next() ,我们试试下
def test():
print("----start-----")
a = 0
b = 1
for i in range(14):
print("-----1------")
yield b
a,b=b,a+b
print("--------2-----")
print("--------3---------")
a=test()
print(next(a))
打印结果:
----start-----
-----1------
1 # b的值取出来一个 , 当它到yield 取到值的时候就停止, 等你下次继续掉
我再用一个next()看看结果是什么?
----start-----
-----1------
1
--------2-----
-----1------
1
通过结果我们可以看出, 在yield 后边的代码继续执行 ,遇到了for循环 继续执行 然后到了yield 停止 把值返回。
这就是生成器代码的执行过程