迭代器和生成器

为什么要有迭代器?

对于序列类型:字符串、列表、元组,我们可以使用索引的方式迭代取出其包含的元素。但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器

什么是迭代器协议?

1、迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么引起一个Stopiteration异常,以终止迭代(只能往后走,不能往前进)

2、可迭代对象:实现了迭代器协议的对象(如何实现:对象定义一个__iter__()方法 )(即内置有__iter__方法的对象)

3、协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象

4、迭代器对象:可迭代对象执行obj.__itre__()得到的结果就是迭代器对象,即指内置有__iter__又内置有__next__方法的对象

例如: open('a.txt').__iter__()     open('a.txt').__next__()

注意:迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象

dic={'a':1,'b':2,'c':3}
iter_dic=dic.__iter__()  #得到迭代器对象,迭代器对象即有__iter__又有__next__,但是:迭代器.__iter__()得到的仍然是迭代器本身
iter_dic.__iter__() is iter_dic  #True

print(iter_dic.__next__())  #等同于next(iter_dic)

将数据类型变成可迭代对象:调用对象内部__iter__方法,如果没有__iter__方法就不是可迭代对象

什么是for循环?

for循环的本质:for循环所有对象,全都是使用迭代器协议,基于迭代器协议提供

#基于for循环,我们可以完全不再依赖索引去取值
dic={'a':1,'b':2,'c':3}
for k in dic:
    print(dic[k])

#for循环的工作原理
#1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
#2:执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
#3:重复过程2,直到捕捉到异常StopIteration,结束循环



#for循环可以循环函数,这是其他语言没有的
def test():
    for i in range(1000):
        yield '鸡蛋%s'%i

mj=test()
for jidan in mj:
    print(jidan)


迭代器的优缺点

优点:1、提供一种统一的,不依赖于索引的迭代方式

           2、惰性计算,节省内存

缺点:1、无法获取长度(只有在next完毕才知道到底有几个值)

            2、一次性的,只能往后走,不能往前退(要注意之前__next__到哪个位置)

 

什么是生成器?

可以理解为一种数据类型,其自动实现了迭代器协议 (其他的数据类型需要调用自己内置的__iter__方法),所以生成器就是可迭代对象。

生成器分类及在python中的表现形式:(python中有两种不同的方式提供生成器)

1、生成器函数:常规函数定义,但是使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。

   iter.__next__()    iter.__next__()         不会重新从头开始运行

好处:

可以在  __next__()  后面加代码,直接对数据进行处理,不用等所有数据都处理完才执行

2、生成器表达式:类似于列表推导,但是生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表。

例如:(i for i in range(10))

#列表解析
['鸡蛋%s'%i for i in range(10)]
['鸡蛋%s'%i for i in range(10) if i>5]    #内部是三元表达式
['鸡蛋%s'%i for i in range(10) if i>5 else i]   #错误,这是四元,没有四元表达式

#生成器表达式
('鸡蛋%s'%i for i in range(10) if i>5)


第一种方法:(其中 l 占用内存)
l=[1,2,3,4]   # l=list(range(1000))
print(sum(l))     

第二种方法:(节省内存)
print(sum(i for i in range(10000000)))

总结:1、把列表解析的 [] 换成 () 得到的就是生成器表达式

           2、列表解析与生成器表达式都是一种便利的编程方式,只不过生成器更省内存

           3、python使用迭代器协议,让for循环变得更加通用。大部分内置函数都是使用迭代器协议访问对象

 

生成器的优缺点

优点:1、延迟操作。在需要的时候才产生结果,而不是立即产生结果,节省内存

 

生成器小结:

1、是可迭代对象

2、实现了延迟计算,节省内存

3、生成器本质和其他的数据类型一样,都是实现了迭代器协议,只不过生成器附加了一个延迟计算省内存的好处,其余的可迭代对象没有这个好处

 

生成器总结:(以生成器函数为例进行总结)

  • 语法与函数类似,return语句换成yield语句在函数中可以写多个
  • 自动实现迭代器协议:对于生成器,Python会自动实现迭代器协议,以便应用到迭代背景中(如for循环,sum函数)。由于生成器自动实现了迭代器协议,所以我们可以调用它的next方法,并且,在没有值可以返回的的时候,

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值