文章目录
前言
迭代器与生成器魔法,这俩就是一对老兄弟,为何说是老兄弟呢,在之前for循环遍历列表元组就是运用的迭代器的思想,函数就类似于生成器,只不过是return换成了yield,之前都出现过他们的表现形式,今天就来详细讲述一下。
迭代器魔法
1. 迭代器协议
对象必须提供一个next方法,执行该方法要么返回迭代的下一项,要么就引起stopteration异常,终止迭代(类似于for循环)
2. 迭代器减少内存的使用
3. next()与__next__()的区别,前者是python内置,后者是数据类型内置
4. 迭代器转换符__iter__()
5. 格式
a = [1,2,3,'l','w']
a1 = a.__iter__() #使a成为迭代器
print(a1.__next__())
print(a1.__next__()) #每次next只读取一个数据
print(a1.__next__())
生成器魔法
1. 格式
语法上和函数类似,自动实现迭代器协议,状态挂起
def product(): #生成器函数简答来说就是把普通函数中return转换为yield,__next__()控制运行
for i in range(100):
print('正在生产包子')
yield '一屉包子%s' %i #yield 遇到则停下(类似于return),再次调用函数则继续后边操作
print('正在卖包子')
p = product()
p.__next__()
p.__next__()
2. 生成器函数的优点
①生成器的好处是延迟计算,一次返回一个结果,也就是说,他不会一次生成所有的结果,这就对于大数据的处理将会有用处。
②生成器还能有效提高代码的可读性。
3. 生成器函数注意内容
①可以保留函数的运行状态,遇到yield就停下来,再次调用__next__()再接着运行。
②对于平常函数,是将数据全部存入列表,增加内存占空间,生成器函数反而减少了内存空间的使用。
4. 生成器表达式、列表解析与三元表达式
a. 列表解析
(1)基本格式
[‘存储’ %i(赋予) (循环)取值]
a = ['爱你%s遍' %i for i in range(1,521)]
print(a)
(2)特殊事项
①列表解析的[]换成()就是生成器表达式。
②生成器表达式比列表解析更省内存。
b. 生成器表达式与列表解析
import time
#列表解析
start_time1 = time.time()
a = sum([i for i in range(5200000)]) #占用内存大,机器容易卡死,耗时长
stop_time1 = time.time()
#生成器表达式
start_time2 = time.time()
b = sum(i for i in range(5200000)) #几乎不占内存,耗时短
stop_time2 = time.time()
print('列表解析结果:',a,'所用时间:',(stop_time1-start_time1))
print('生成器表达式结果:',b,'所用时间:',(stop_time2-start_time2))
5. 生成器相关实例
a. 不可重复迭代
def get_polulation():
with open('人口普查','r',encoding='utf-8') as f: #简单的字典类型数据
for i in f:
yield i
g = get_polulation()
s1 = eval(g.__next__()) #转化字典类型,迭代了一次
print(s1['population'])
all_pop = sum(eval(i)['population'] for i in g) #因上面迭代了一次,此处就少迭代一次
print(all_pop)
for p in g: #前面面迭代完成,从而再次将无法迭代,后面无法得出结果
print('%s %s' %eval(p)['population']/all_pop)
b.生产者消费者模型(两者同时进行)
import time
def consumer(name):
print('我是%s,我准备开始吃包子了' %name)
while True:
baozi = yield
time.sleep(1)
print('%s 很开心的把%s吃掉了' %(name,baozi))
def producer():
c1 = consumer('L') #在生产者运转的同时消费者也在运行
c2 = consumer('W')
c1.__next__()
c2.__next__()
for i in range(10):
time.sleep(1)
c1.send('包子%s' %i)
c2.send('包子%s' % i)
producer()
总结
迭代器是循环遍历的内在,与列表解析比起来,生成器很大程度上减少了内存的使用,这两个应该在程序中起着重中之重的作用。