Python Magic——迭代器与生成器

文章目录


前言

迭代器与生成器魔法,这俩就是一对老兄弟,为何说是老兄弟呢,在之前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()

总结

迭代器是循环遍历的内在,与列表解析比起来,生成器很大程度上减少了内存的使用,这两个应该在程序中起着重中之重的作用。

上一篇:PhpStorm XDebug 远程调试


下一篇:基于猜数字游戏程序逐步完善(C语言基础练习)