美文网首页我爱编程
迭代器(Iterator)

迭代器(Iterator)

作者: 江山画_孤影 | 来源:发表于2018-05-26 14:04 被阅读0次

    迭代是Python最强大的功能之一。先给大家看张图(图来自网络),看不懂没关系,等学完这一章和下一章的内容,最后再回过头看这张图就很清晰了。

    可迭代对象,迭代器,生成器关系概览

    容器(container)

    常见的容器对象有:
    str
    list, deque, ….
    tuple, namedtuple, …
    dict, defaultdict, OrderedDict, Counter, ….
    set, frozensets, ….
    

    可迭代对象(iterable)

    #可迭代对象定义【重点】
    如果对象能实现返回迭代器的__iter__的方法,或者能实现__getitem__方法,
    而且参数是从零开始的索引,这种对象就是可迭代对象。
    
    任何Python序列都可迭代的原因是:它们都实现了 __getitem__ 方法。
    标准的序列不仅实现了 __getitem__ 方法同时还实现了 __iter__ 方法。
    
    #判断对象是否是可迭代对象
    #方法一 isinstance()
    >>>from collections import Iterable  
    >>>mydict = {'a':97,'b':98,'c':99} 
    >>>isinstance(mydict,Iterable)
    True  
    
    >>>nums = map(lambda x:x*2,[1,2,3,4])
    >>>isinstance(nums,Iterable)
    True  
    
    >>>mylist = ['a','b','c','d'] 
    >>>isinstance(enumerate(mylist),Iterable)
    True  
    以及等等.......
    
    #方法二 iter()
    >>>mylist = [1,2,3,4]
    >>>iter(mylist)
    <list_iterator object at 0x01DC94F0>
    
    >>>iter(mydict)
    <dict_keyiterator object at 0x005C4420>
    
    >>>iter(nums)
    <map object at 0x00359FB0>
    
    >>>iter(enumerate(mylist))
    <enumerate object at 0x0213FCD8>
    
    >>>x = 123
    >>>iter(x)
    TypeError: 'int' object is not iterable
    #不可迭代的对象,会报错.
    
    此外还有更多的对象同样也是可迭代对象,比如打开的状态的files,sockets等等
    简单来说:绝大多数的容器都是可迭代对象,但也有例外,比如Bloom filter
    虽然Bloom filter可以用来检测某个元素是否包含在容器中,但是并不能从容器中获取其中的每一个值,
    因为Bloom filter压根就没把元素存储在容器中,而是通过一个散列函数映射成一个值保存在数组中。
    

    迭代器( iterator)

    #迭代器协议
    所谓的迭代器协议是指:对象需要提供__next__方法,
    它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代。
    
    #迭代器定义
    实现了迭代器协议的对象就是迭代器
    
    在python语言内部,迭代器用于支持:
    1.for 语句
    2.构建和扩展集合类型
    3.逐行遍历文本文件
    4.列表推导,字典推导,集合推导
    5.元组拆包
    6.调用函数时,使用*拆包实参
    
    #for语句原理【重点】
    在python中,for语句用于迭代,而while语句才是用于真正的循环
    
    下面这个过程背后其实是有迭代器的,只不过我们看不到:
    >>>s = 'abc'
    >>>for i in mystring:
    >>>    i
    
    真实过程用while语句改写是这样:
    >>> s = 'abc'
    >>> it = iter(s) #通过iter方法从可迭代对象s中获取迭代器对象it
    >>>while True:
    >>>    try:
    >>>        next(it) #在迭代器上调用next(),获取下一个值
    >>>    except StopIteration: #如果没有值了,抛出StopIteration异常
    >>>        del it #释放对it的引用,即废弃迭代器对象
    >>>    break #退出循环
    
    小结【重点】
    在for语句内部,实际是通过调用iter()方法将可迭代对象转换成迭代器对象,
    然后再重复调用next()方法实现的.for语句会自动捕获 StopIteration 异常,
    并在捕获异常后终止迭代.所以,对容器对象调用 iter() 方法再使用 for 语句是多余的,比如:
    >>>for i in iter(list) #多此一举
    

    可迭代对象与迭代器的关系【重点】

    1.从可迭代的对象中获取迭代器对象
    
    >>>mylist = [1,2,3,4]  #可迭代对象
    >>>iter(mylist)  #通过iter()方法从可迭代对象mylist中获取迭代器对象
    <list_iterator object at 0x01D49FB0>
    
    2.可迭代对象不是迭代器,但是所有的迭代器都是可迭代对象
    
    #可迭代的对象一定不能是自身的迭代器.也就是说,可迭代的对象
    #必须实现 __iter__ 方法,但不能实现 __next__ 方法
    
    >>>mylist = [1,2,3,4]
    >>>next(mylist)
    TypeError: 'list' object is not an iterator
    
    >>>from collections import Iterable
    >>>mylist = [1,2,3,4]
    >>>isinstance(iter(mylist),Iterable)
    True 
    
    #因为迭代器实现了__iter__方法,根据可迭代对象的定义,迭代器自然是可迭代对象
    #而且特殊的一点是迭代器的__iter__ 方法必须返回自身
    >>>iter([1,2,3,4]) #迭代器对象
    <list_iterator object at 0x00619450>
    >>>iter(iter([1,2,3,4])) #对迭代器对象使用iter(),返回自身
    <list_iterator object at 0x00619450>
    
    
    
    3.迭代器只能使用一次,如果想再次迭代,要重新构建迭代器。
    
    >>>mylist = [1,2]
    >>>it = iter(mylist)
    >>>next(it)  #1
    >>>next(it) #2
    >>>next(it) #抛出异常,废弃迭代器对象,也就是it不能再用了
    
    
    
    >>>it1 = iter(mylist)
    >>>id(it1)   #6264048
    >>>next(it1)
    >>>next(it1)
    >>>it2 = iter(mylist) #再次创建迭代器对象
    >>>id(it2)   #6266800
    >>>next(it2)
    >>>next(it2)
    it1和it2都是迭代器对象,但这两个对象显然不是同一个对象
    >>>it1 is it2
    False
    
    >>>it2 = iter(it1) #传入迭代器本身没用,必须传入之前构建迭代器的可迭代对象即mylist
    >>>it2
    <list_iterator object at 0x004E9FB0>
    
    #小结
    因为迭代器只需 __next__ 和 __iter__ 两个方法,所以除了调用
    next() 方法,以及捕获 StopIteration 异常之外,没有办法检查是否
    还有遗留的元素。此外,也没有办法“还原”迭代器。如果想再次迭代,
    那就要调用 iter(...),传入之前构建迭代器的可迭代对象。传入迭代
    器本身没用,因为前面说过 Iterator.__iter__ 方法的实现方式是返
    回实例本身,所以传入迭代器无法还原已经耗尽的迭代器。
    

    相关文章

      网友评论

        本文标题:迭代器(Iterator)

        本文链接:https://www.haomeiwen.com/subject/okfalftx.html