zoukankan      html  css  js  c++  java
  • 可迭代对象与迭代器

    我们已经知道可以对 list、tuple、str等类型的数据使用for…in…的循环语法从其中依次拿到数据进行使用,我们把这样的过程称之为遍历,也叫迭代。

    不是所有的数据类型都可以放在**for…in…**中进行迭代的,比如 int 类型…

    什么是可迭代对象?


    通过自定义一个容器类型MyList,在将一个存放了多个数据的MyList对象放到了 for…in… 的语句中,发现 for…in… 并不能从中依次取出一条数据返回给我们,也就是说我们即便封装了一个可以存放多条数据的类型却并不能被迭代使用。

    我们把可以通过 for…in… 这类语句迭代读取一条数据供我们使用对象称之为 可迭代对象(iterable)。

    如何判断一个对象是否可以迭代?
    可以使用isinstance()判断一个对象是否是Iterable对象。

    from collections import Iterable

    class Classmates(object):

    def __init__(self):
    self.names = list()

    def add(self,name):
    self.names.append(name)

    def __iter__(self): #返回可迭代对象自己
    return self
    """如果想让一个对象成为一个'可以迭代的对象',即可以使用for,那么必须实现__iter__方法"""


    classmate = Classmates()

    print ("判断classmate是否是可以迭代的对象",isinstance(classmate,Iterable))


    可迭代对象的本质

    每迭代一次(即在for...in...中每循环一次)都会返回对象中的下一条数据,一直向后读取数据直到迭代了所有数据后结束。

    那么在这个过程中就应该有一个存在去记录每次访问到了第几条数据,以便每次迭代都可以返回下一条数据。我们把这个能帮助我们进行数据迭代的存在称之为“迭代器”(Iterator)。

    可迭代对象的本质就是可以向我们提供一个这样的存在,即迭代器帮助我们对其进行迭代遍历使用。

    可迭代对象通过__iter__方法向我们提供了一个迭代器,我们再迭代一个可迭代对象的时候,实际上就是先获取该对象提供的一个迭代器,然后通过这个迭代器来依次获取对象中的每一个数据。

    那么也就是说,一个具备了 iter 方法的对象,就是一个可迭代对象。

    如何判断一个对象是否是迭代器?
    可以使用 isinstance() 判断一个对象是否是Iterator对象。

    iter()函数 与 next()函数

    list、tuple等都是可迭代函数,我们可以通过iter()函数获取这些可迭代对象的迭代器。然后我们可以对获取到的迭代器不断使用next()函数来获取下一条数据。 iter()函数实际上就是调用了可迭代对象的 __iter__ 方法。

    附:需要注意的是,当我们已经迭代完最后最后一个数据之后,再次调用 next()函数 会抛出 StopIteration、IndexError的异常,来告诉我们下标越界,所有的数据都已经迭代完成,不再执行next()函数了。

    class ClassIterable(object):

    def __init__(self):
    self.names = list()
    self.current_num = 0

    def add(self,name):
    self.names.append(name)


    def __iter__(self): #返回自己对象引用
    return self


    def next(self):
    if self.current_num < len(self.names): #判断当前的迭代是否已经完成
    wet = self.names[self.current_num]
    self.current_num+=1
    return wet

    else:
    raise StopIteration


    classmethod = ClassIterable()
    classmethod.add('zhangshan')
    classmethod.add('lisi')
    classmethod.add('wangwu')
    classmethod.add('zhaoliu')

    for name in classmethod:
    print name
    time.sleep(2)

    迭代器 (Iterator)的本质

    通过上面代码的分析,我们已经知道,迭代器是用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用 next()函数的时候,迭代器会向我们返回它所记录位置的下一个位置的数据。

    实际上,在使用next()函数的时候,调用的就是迭代器对象的 next 方法 (Python3中是对象的 next 方法, Python2中是对象的 next()方法)。所以我们要想构造一个迭代器,就要实现它的 next 方法。 但这还不够,python要求迭代器本身也是可迭代的,所以我们还要为迭代器实现 iter 方法,而 iter 方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的 iter 方法 返回自身即可。

    一个实现了 iter 方法 和 next 方法 的对象,就是迭代器。

    for…in… 循环的本质
    for item in Iterable 循环的本质就是先通过 iter()函数获取可迭代对象 Iterable的迭代器,然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item,当遇到 StopIteration的异常后循环结束。

    我们发现迭代器最核心的功能就是可以通过 next()函数 的调用来返回下一个数据。如果每次返回的数据值不是在一个已有的数据集合中读取的,而是通过程序按照一定的规律计算生成的,那么也就意味着可以不用再依赖一个已有的数据集合,也就是说不用再将所有的数据都一次性缓存下来供后续依次读取,这样可以节省大量的存储(内存)空间。



  • 相关阅读:
    设计模式开始--工厂模式
    设计模式开始--UML类之间关系表示
    设计模式开始1--不明觉厉
    Gas Station
    Validate Binary Search Tree
    Word Ladder
    (转)基于快速排序的TOPK算法
    Number of 1 Bits
    Word Search
    Rotate Array
  • 原文地址:https://www.cnblogs.com/jack1989/p/10797775.html
Copyright © 2011-2022 走看看