生成器(生成器的本质是保存了一套生成值的算法,每调用一次生成一个值):
目标:需要一个非常大的列表,里面有很多元素,还不想占用太大内存空间。
生成器组成方式一:
将生成式的列表改为元组即可。
x = [x for i in range(5)] ---------------> x = (x for in range(5))
生成器组成方式二:
包含“yield”的函数
def creat_num():
print('-----start------')
a,b = 0,1
for i in range(5):
yield b =============>带有关键字“yield”的函数就不再称为函数了,统计称为生成器。“yield”在此将程序拦腰斩断,程序每执行完包含“yield”关键字的这行代码就暂停(并且返回“yield”后面的值,
相当于return b),直到再次被next()调用时再继续往下走。
思考:把yield放在最后一行,前面的代码负责生成要返回的值,yield负责暂停循环和return生成的值。
a,b = b,a+b
print('-----stop-------')
a = creat_num() ===========>调用这个“函数”时实际返回的是一个对象
next(a) ========>在生成器对象里包含一个self.__next__()方法,等价于next(self)
for i in a: =============>注意:尽管生成器是一个对象,依然可以用for来遍历。
print(i)
def test():
a = 0
while a < 5:
temp = yield a ==========>注意:因为基本语法规定碰到“=”先执行右边再执行左边,所以此处执行右边后即暂停,所以temp就得不到值了,下次开始时相当于从“temp=”开始执行,即temp得到的值为空。
要想让temp得到值可以使用t.__send__('haha')方法将一个值传进去(即:haha),同时__send__也具有__next__的本领(即让生成器继续往下走一步)。
print(temp)
i+=1
t = test()
t.__next__()
t.__next__() ========> 输出结果为None
生成器组成协程:
def test1():
while 1:
print('--1--')
yield None
def test2():
while 1:
print('--2--')
yield None
t1 = test1()
t2 = test2()
while 1: =======>程序有了“暂停”功能就可以循环切换任务来执行了(即:协程)
t1.__next__()
t2.__next__()