Python的迭代器

迭代器

1、什么是迭代器?

  迭代器指的是迭代取值的工具,迭代是一个重复的过程,每一次重复都是基于上一次的结果单纯的重复不是迭代(更新迭代)
每一次对过程的重复称为一次“迭代,而每一次迭代得到的结果会作为下一次迭代的初始值。
# 举例:单纯的重复,这不是迭代
# while True:
#     name = input(">>")

# 举例:这是迭代,每一次重复都是基于上一次的结果。爸爸-->儿子-->孙子,下述while循环才是一个迭代过程
# count = 0
# while count<5:
#     print(count)
#     count += 1

2、为何要有迭代器? 

迭代器是用来迭代取值的工具,而涉及到把多个值循环取出来的类型有列表、字符串、元组、字典、集合、文件
# 对于list,tuple,string
l = ['lsj','tianjing']
i = 0
while i < len(l):
    print(l[i])
    i += 1
# 上述迭代取值的方式只适用于有索引的数据类型例如:列表、字符串、元组。
# 没有索引的数据类型:字典、集合、打开的文件,如果我想迭代取值该怎么办?这就是基于索引迭代取值的局限性。
# 为了解决基于索引迭代器取值的局限性。python必须提供一种能够不依赖于索引的取值方式,这就是迭代器

3、可迭代对象

  可迭代对象(iterable):但凡内置有__iter__方法的都称之为可迭代的对象。

# 如下所示:字符串、列表、元组、字典、集合、打开的文件都有内置__iter__方法都是可迭代对象
# 定义一个空字符串
s1=''
s1.__iter__()
# 定义一个列表
l=[]
l.__iter__()
# 定义一个元组
t=()
t.__iter__()
# 定义一个字典
d={'a':1}
d.__iter__()
# 定义一个集合
set1={1,2,3}
set1.__iter__()
# 打开一个文件
with open('a.txt',mode="w") as f:
    f.__iter__()
    # pass
# 不依赖于索引的取值方案,所以要用到迭代器
# 调用可迭代对象下的__iter__方法会将其转换成迭代器对象,转换成功后就不依赖于索引取值了
d = {"a":1,"b":2,"c":3}
res = d.__iter__()
print(res)
# 不依赖于索引的取值方案,所以要用到迭代器
# 调用可迭代对象下的__iter__方法会将其转换成迭代器对象
d = {"a":1,"b":2,"c":3}
d_iterator= d.__iter__()  # 此时的res就是可迭代器对象
# print(d_iterator)

# d_iterator.__next__() # 取值
# print(d_iterator.__next__())  # 得到字典的key  a
# print(d_iterator.__next__())  # 得到字典的key  b
# print(d_iterator.__next__())  # 得到字典的key  c
#
# print(d_iterator.__next__())  # 字典中有三个值,再去一次会抛出异常:StopIteration,表示迭代器没有值可取了

# 把该迭代器想象一只老母鸡,这个老母鸡是有寿命的,这只老母鸡一生中只能下200个鸡蛋,下一个身体机能也有损耗,当下到最后一个时候,遇到StopIteration,会死掉
# 使用while循环代表上面四个取值,如下:
while True:
    print(d_iterator.__next__())

"""结果如下:
a
b
c
StopIteration
"""
# 如何解决上面的异常?使用try...except
while True:
    try:
        print(d_iterator.__next__())
    except StopIteration:
        break
"""运行结果如下:
a
b
c
"""
# 对同一迭代器取值,在取干净的情况下再一次取值,就会取不到。
print("====================================")
while True:
try:
print(d_iterator.__next__())
except StopIteration:
break
# 运行结果:为空
# 如果我想在去一便呢?需要再次造一次迭代器
d_iterator = d.__iter__()
while True:
    try:
        print(d_iterator.__next__())
    except StopIteration:
        break
# 运行结果如下:
"""
a
b
c
"""
# 迭代器与for循环工作原理
# 使用while 循环体现迭代器功能,比较麻烦,有无更简单的方案,那就是for循环

# 3、可迭代对象与迭代器对象详解
# 3.1、可迭代对象("可以转换成迭代器的对象"):内置有__iter__方法对象
#         可迭代对象.__iter__():得到迭代器对象
#         可迭代对象例如:字符串、元组、列表、集合、字典
# 3.2、迭代器对象:内置有__next__方法并且内置有__iter__方法的对象
#           迭代器对象.__next__():得到迭代器的下一个值
#           迭代器对象.__iter__():得到迭代器的本身,(调用和没调用一样)
#           迭代器对象例如:只有文件时迭代器对象
# 总结:可迭代对象不是可迭代器对象,但是迭代器对象是可迭代的对象


# dic = {"a":1,"b":2,"c":3}
# dic_iterator = dic.__iter__()
#
# print(dic_iterator is dic_iterator.__iter__())  # True,也就是说调用迭代器的__iter__()跟没调一样


# for循环会调用iter方法
# for x in 迭代器对象.__iter__(): 
#     pass

# 定义一个字典
dic = {"a":1,"b":2,"c":3}
# 在没有使用迭代器的时候直接使用for寻魂,简单粗暴
for k in dic:
    print(k)
"""
a
b
c
"""

# 使用迭代器会如下所示:
dic_iterator = dic.__iter__()
while True:
    try:
        print(dic_iterator.__next__())
    except StopIteration:
        break
"""
a
b
c
"""
# 总结:for循环的工作原理
# 1、d.__iter__()得到一个迭代器对象
# 2、迭代器对象.__next__()拿到一个返回值,然后该返回值赋值给k
# 3、循环往复步骤2,直到抛出异常StopIteration的异常,for循环会不捉异常后结束循环
with open("test018_07a.txt",mode='rt',encoding='utf-8') as f:
    # for line in f:  # f.__iter__() 迭代器对象调用__iter__(),结果还是它本身
    for line in f.__iter__():
        print(line)
"""f = f.__iter__(),运行结果如下
aaa

bbb

ccc

"""

 迭代器的优缺点:

  基于索引的迭代取值,所有迭代的状态都保存在了索引中,而基于迭代器实现迭代的方式不在依赖索引,所有迭代的状态就保存在迭代器中。

优点:

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

  2、惰性计算:懒汉式计算,只有在需要数据的时候才去调用next来计算出一个值,就迭代器本身而言,同一时刻在内存中之哟一个值。

缺点:

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

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

验证range()是否为可迭代对象?

 

>>> range(1,3).__iter__
<method-wrapper '__iter__' of range object at 0x000001C9D9C90810>
>>> range(1,3).__next__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'range' object has no attribute '__next__'

 

# 验证字典取keys()是否为可迭代对象?
>>> {"a":1}.keys()
dict_keys(['a'])
>>> {"a":1}.keys().__iter__
<method-wrapper '__iter__' of dict_keys object at 0x000001C9D9C90820>
>>> {"a":1}.keys().__next__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'dict_keys' object has no attribute '__next__'

 

 

4、如何使用迭代器?

 

 

 

posted @ 2020-04-05 00:05  思江  阅读(246)  评论(0编辑  收藏  举报