什么是生成器:
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
创建生成器方法1:
ge = (x**2 for x in range(100000000000000000000))
print(ge)
print(type(ge))
如果要将ge中的数字一个一个打印出来,可以通过next()函数获得生成器的下一个返回值。生成器保存的是算法,每次调用next(ge),就计算出ge的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的异常。当然,这种不断调用next()实在是太变态了,正确的方法是使用for循环,因为生成器也是可迭代对象。所以,我们创建了一个生成器后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration异常。
创建生成器方法2:
yield 值
1、调用函数,得到一个生成器对象。这个函数没有执行
2、next调用1得到的对象,如果遇到了yield,代码会阻塞,next的返回值就yield后的值
例如:
def fib(times):
n = 0
a,b = 0,1
while n
yield b
a,b = b,a+b
n+=1
return 'done'
上述第一种和第二种方法,一旦生成器确定,算法不能改变。这里的例子,定义了变量(temp),可以使用send发送参数,发给这里变量。根据这个变量的值的不同,可以改变算法的逻辑。所以,这种写法的作用:在运行过程中,可以改变算法。
def gen():
i = 0
while i<1000:
temp = yield i
if temp==True:
#逻辑代码
print('执行A计划')
i+1
else:
#逻辑代码
print('执行B计划')
i+=2
myGenerator = gen()
ret = next(myGenerator)
print(ret)
#1、为当前停止的代码的左侧变量赋值 2、生成器往下走一个行,返回yield值
ret = myGenerator.send(True)
print(ret)
ret = myGenerator.send(False)
print(ret)