15、迭代器

一、迭代器和迭代

迭代器即用来迭代取值的工具,迭代是重复反馈过程的活动,其目的通常是为了逼近所需的目标或结果,每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值,单纯的重复并不是迭代而是循环

# 下面这个是就是一个迭代过程
names = ['吴彦祖', '彭于晏', '古天乐', '胡歌', '我']
i = 0
while i < len(names):
    print(names[i])
    i += 1

可是迭代功能十分常用,这时候我们就要把它写成一个功能经常调用,我们可以写成函数

names = ['吴彦祖', '彭于晏', '古天乐', '胡歌', '我']
msg = '即将秃头也不失帅气的我'


def func(items):
    i = 0
    while i < len(items):
        print(items[i])
        i += 1


func(msg)
func(names)

上面的方法通过索引的方式进行迭代取值,实现简单,但仅适用于序列类型:字符串,列表,元组。对于没有索引的字典、集合等非序列类型,必须找到一种不依赖索引来进行迭代取值的方式,这就用到了迭代器。

二、迭代器的使用

1、可迭代对象

内置有__iter__方法的对象都是可迭代对象,字符串、列表、元组、字典、集合、打开的文件都是可迭代对象

[1, 2, 3].__iter__()
{'name': 'poco'}.__iter__()

2、迭代器对象

内置有__iter__和有__next__方法的都是迭代器对象

调用:可迭代对象.__iter__()  --> 返回迭代器对象
调用:迭代器对象.__next__()  --> 返回的是下一个值 
dic = {'姓名':'poco','年龄':18,'性别':'男性'}
iter_dic = dic.__iter__()  # 把可迭代对象转成迭代器对象

print(iter_dic.__next__())
print(iter_dic.__next__())
print(iter_dic.__next__())

优化版

dic = {'姓名': 'poco', '年龄': 18, '性别': '男性'}
iter_dic = iter(dic)  # iter(dic)等于dic.__iter__()

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

三、for循环原理

有了迭代器后,我们便可以不依赖索引迭代取值了,使用while循环的实现方式如下

dic = {'姓名': 'poco', '年龄': 18, '性别': '男性'}
iter_dic = iter(dic)

while True:
    try:  # 捕捉异常
        print(next(iter_dic))
    except StopIteration:  # 抛出异常
        break

其实for循环就和我上面写的while循环原理是一样的。

for 循环在工作时,首先会调用可迭代对象dic内置的iter方法拿到一个迭代器对象,然后再调用该迭代器对象的next方法将取到的值赋给iter_dic,执行循环体完成一次循环,周而复始,直到捕捉StopIteration异常,结束迭代。

dic = {'姓名': 'poco', '年龄': 18, '性别': '男性'}
for k in dic:
    print(k)

四、迭代器总结

1、优点

1、为序列和非序列类型提供了一种统一的迭代取值方式。

2、惰性计算:不消耗内存,迭代器对象表示的是一个数据流,可以只在需要时才去调用next来计算出一个值,就迭代器本身来说,同一时刻在内存中只有一个值,

2、缺点

1、除非取尽,否则无法获取迭代器的长度

2、只能取下一个值,不能回到开始,更像是‘一次性的’,迭代器产生后的唯一目标就是重复执行next方法直到值取尽,否则就会停留在某个位置,等待下一次调用next;若是要再次迭代同个对象,你只能重新调用iter方法去创建一个新的迭代器对象,如果有两个或者多个循环使用同一个迭代器,必然只会有一个循环能取到值。

posted @ 2021-03-30 19:30  黑影Poco  阅读(67)  评论(0)    收藏  举报