生成器的生活实例
每天要吃一个鸡蛋
1,超市买一框鸡蛋,60个,管60
2,养一只母鸡,母鸡每天下蛋,60天,一天下一个蛋
对于计算机页言
关注的是数据的空间
相当于本例子中,鸡蛋的空间
1,60个,比较占空间的
2,1个鸡蛋,比较省空间
对于生活而言,方式2,还是比较新鲜的
。。
列表生成式
li = [i for i in range(100000000000)
结果
在内存中划一块空间
存储数据【1,2,。。。。100000000000】
写一个公式出来
需要用的时候,公式给我算出结果,给我数据
什么是生成器?
通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的,而且创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间,在Python中,这种一边循环一边计算的机制,称为生成器:generator
生成器是一个特殊的程序,可以被用作控制循环的迭代行为,python中生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停,而可以使用next()函数和send()函数恢复生成器。
生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用,但是,不同于一般的函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这样消耗的内存数量将大大减小,而且允许调用函数可以很快的处理前几个返回值,因此生成器看起来像是一个函数,但是表现得却像是迭代器
创建一个生成器
通过列表生成式
把列表生成式中的[]
替换为()
得到的就是一个生成器
通过函数的改造
在函数中添加yield
那么该函数的调用,就是在创造一个生成器
yield
英 [jiːld] 美 [jiːld]
v.
出产(作物);产生(收益、效益等);提供;屈服;让步;放弃;缴出
n.
产量;产出;利润
函数中如果有了yield
该函数就不是一个普通的函数了
它是一个生成器函数
生成器函数名()
可以得到一生成器
这种效果类似于
类名()
得到一个对象
生成器的使用
生成器对象.__next__
()
执行生成器函数中的代码
同时返回yield后面的数据
yield的效果
相当于一个保存点
如果生成器调用__next__
方法,会从上一个保存点开始,直到遇见了yield就会停住,同时返回yield后面的数据
for循环遍历的本质
for 变量 in 列表:
print(变量)
第一步,它会调用列表的__iter__
方法,得到一个迭代器
obj = li.__iter__()
# obj.__next__()
# obj.__iter__()
第二步,针对这个迭代器,进行方法的调用
它会调用这个迭代器的__next__
方法
并且把值,赋给 变量
第三步,打印输出这个变量
第四步,继续打印输出这个变量
第五步。。。继续,直到无法获得变量,遇到一个异常
上述的第三,四五步可以通过一个无限循环来解决
在循环中捕捉这个异常,捕捉成功就退出无限循环,让程序结束
li = ["张飞", "马超"]
obj = li.__iter__()
while True:
try:
i = obj.__next__()
print(i)
except StopIteration as t:
break