美文网首页
跟你深入剖析可迭代对象和迭代器的区别和联系

跟你深入剖析可迭代对象和迭代器的区别和联系

作者: 隔壁老甘 | 来源:发表于2020-05-12 11:31 被阅读0次

导语

可迭代对象和迭代器是经常碰到但又很容易混淆的两个概念,所以今天小编跟大家深入剖析一下可迭代对象和迭代器的区别。认真看完本文,你将收获:

  • 理解什么是可迭代对象
  • 理解检查可迭代对象的方法
  • 理解什么是迭代器
  • 可迭代对象和迭代器的关系

事不宜迟,我们马上开始吧!

可迭代对象

要理解可迭代对象,那首先要搞清楚迭代的概念。关于迭代,维基百科是这样子定义的:

迭代是重复反馈过程的活动,其目的通常是为了接近并到达所需的目标或结果。每一次对过程的重复被称为一次“迭代”,而每一次迭代得到的结果会被用来作为下一次迭代的初始值。

从这个定义中,我们大概可以知道迭代是对某一个过程的重复。其实在程序中,迭代也是类似的,它是一种遍历集合元素的方式,请看下面的示例1。

# 示例1for i in [1,2,3]:    print(i)

输出结果:

123

在示例1中,解释器重复地从列表中取出元素并打印,直到遍历结束为止,这就是一个迭代的过程。可见,可迭代对象可以在for循环中遍历元素。

那什么样的对象才是一个可迭代对象?事实上,只要实现 __ iter __ 方法或者实现 __ getitem __方法而且其参数从0开始索引,那么该对象就是可迭代对象,请看示例2。

#示例2class Vector(object):    def __init__(self,components):        self.components = list(components)            def __iter__(self):        return iter(self.components)V1 = Vector([1,2,3])for i in V1:    print(i)

输出结果:

123

从示例2中可见,Vector类实现了 __ iter __方法,解释器可以从Vector类对象中重复地取出元素并打印。如果要检查某一个对象是否为可迭代对象,其实可以使用isinstance( )函数,该函数用于判断对象是否为某一类型,但是用这个函数判断不一定准确(原因后面会说到)。

from collections import Iterableprint(isinstance(V1,Iterable))#True

如果我们只是实现了 __ getitem __ ()方法,情况又会怎么样呢?请看示例3。

# 示例3from collections import Iterableclass Vector(object):    def __init__(self,components):        self.components = list(components)        def __getitem__(self,index):        return self.components[index]    V1 = Vector([1,2,3])for i in V1:    print(i)print(isinstance(V1,Iterable))

输出结果:

123Flase

从示例3中可看到,Vector实现了 __ getitem __ 方法,解释器可以对V1进行迭代并打印元素,但是!使用isinstance()判断时,返回的结果居然是False。明明可以使用for循环来迭代元素,为什么是判断是Flase呢?事实上,如果可迭代对象只是实现了 __ getitem __ 的话,abc.Iterable是不考虑该方法的,这便导致了isinstance()判断不准确。更准确的方法应该是调用iter()函数,如果该对象不可迭代,就会抛出TypeError的错误。我们尝试使用iter()来判断一下。

# 示例4print(iter(V1))#<iterator object at 0x000001B262E35518>#去掉__getitem__方法后print(iter(V1))#TypeError: 'Vector' object is not iterable

从示例4中可以看到,对于可迭代对象,iter()会返回< iterator object at xxxx >。当去掉 __ getitem __ ()方法后再检查时,便抛出TypeError错误。iter()函数用于生成一个迭代器,也就是说可以返回一个迭代器的就是一个可迭代对象。

该对象之所以能迭代,是因为实现了__ iter __ ()方法。当使用for循环时候,解释器会检查对象是否有__ iter __ ()方法,有的话就是调用它来获取一个迭代器。所以没有 __ iter __ ()方法但实现了__ getitem __ (),解释器会创建一个迭代器,尝试从0开始按顺序遍历元素。如果尝试失败,Python便会抛出TypeError错误。

那么Python内置类型中究竟有哪些可迭代对象呢?我们一起盘点一下吧。

  • list
  • dict
  • tuple
  • set
  • string

其实盘点出来的都是序列,所以说任何序列都是可迭代的对象, 其原因在于他们至少都会实现__ getittem __ 方法(序列都可以通过索引获取元素)。

迭代器

在介绍可迭代对象时候说到,当使用for循环时候,解释器会检查对象是否有__ iter __ ()方法,有的话就是调用它来获取一个迭代器。那么究竟什么是迭代器呢?

其实迭代器是实现了__ iter __ 方法和 __ next __ 方法的对象。__ iter __ 方法用于返回迭代器本身,而 __ next __ 用于返回下一个元素。我们自定义一个迭代器,以斐波那契数列为例说明一下其内部的执行情况,看示例5。

# 示例5import itertoolsclass Fib:    def __init__(self):        self.pre = 0        self.cur = 1    def __iter__(self):        return self        def __next__(self):        p = self.cur        self.cur += self.pre        self.pre = p        return pf = Fib()a = list(itertools.islice(f,0,10))print(a)#[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

从示例5中__ iter __ ()返回了迭代器对象本身,以便在使用可迭代对象的地方(如for循环中)使用迭代器,而 __ next __ ()则通过计算返回下一个元素。我们再一起看看下面的示例6。

#示例6>>>s = 'ABCD'>>>it = iter(s)>>>while True:print(next(it))ABCD---------------------------------------------------------------------------StopIteration                             Traceback (most recent call last)<ipython-input-4-d09d5cde4495> in <module>()----> 1 while True:print(next(it))StopIteration:>>> list(it)[]>>>list(iter(s))['A','B','C','D']

在示例6中先定义一个字符串的可迭代对象,通过iter()函数返回一个迭代器(会自动调用对象的__ iter __ 方法),然后在循环中通过next()取值并打印(会自动调用对象 __ next __ ()方法),通过next()方法一个个地遍历可迭代对象中的元素,当遍历结束,便会抛出StopIteratioin异常,这时迭代器也没用了,如果要再次迭代,就要使用iter()函数重新构建迭代器。

通过示例5和示例6,我们可知道迭代器是一个可以记住遍历位置的对象,其内部有一个状态用于记录迭代所在的位置,以便下次迭代时候能取出正确的元素。迭代器就像一个懒人一样,当你需要数据时候才会返回给你,否则就在等待下一次的调用。

如果要检查某个对象是否为迭代器,最好的方式是使用isinstance( )函数,见示例7。

# 示例7from collections import Iterator f = Fib()print(isinstance(f,Iterator)) #True

好了,说了那么多,究竟迭代器哪些用处呢?其实在Python语言内部,迭代器用于支持:

  • for 循环
  • 构建和扩展集合类型
  • 逐行遍历文本文件
  • 列表推导、字典推导和集合推导
  • 元组拆包
  • 调用函数时,使用*拆包

可迭代对象和迭代器的关系

  • 可迭代对象不一定是迭代器,迭代器一定是可迭代对象。因为迭代器一定会实现 __ iter __ 方法,而可迭代对象尽管实现了 __ iter __ 也不一定实现 __ next __方法。

  • Python 从可迭代对象中获取迭代器,根据示例6的例子,我们知道先是使用iter()函数在迭代对象中获取迭代器,然后使用next()来获取下一个元素,关系如下图所示。

总结

  • 可迭代对象实现了 __ iter __ 方法或者实现 __ getitem __方法而且其参数从0开始索引。
  • 使用iter()函数判断可迭代对象更准确
  • 任何序列都是可迭代对象
  • 迭代器对象实现了 __ iter __ 和 __ next __方法。
  • 迭代器是一个可以记住遍历位置的对象,其内部有一个状态用于记录迭代所在的位置,以便下次迭代时候能取出正确的元素
  • 检查对象是否为迭代器最好的方式是调用isinstance()方法。

以上就是小编今天跟大家分享的内容了,如果有什么疑问记得联系小编哦~

公众号:CVpython,专注于分享Python和计算机视觉,我们坚持原创,不定期更新,希望文章对你有帮助,快点关注我们吧~

相关文章

  • 跟你深入剖析可迭代对象和迭代器的区别和联系

    导语 可迭代对象和迭代器是经常碰到但又很容易混淆的两个概念,所以今天小编跟大家深入剖析一下可迭代对象和迭代器的区别...

  • [笔记]可迭代对象、迭代器、生成器

    为了更深入一点理解可迭代对象和迭代器,读了几篇不错的文章: Python实践18-可迭代对象和迭代器 - 曾月天的...

  • Python12--迭代器

    1.迭代器 要理解迭代器,首先需要明白迭代器和可迭代对象的区别。一个一个读取、操作对象称为迭代,Python 中,...

  • Python之迭代器

    >可迭代对象和迭代器傻傻分不清 之前自己一直没搞明白可迭代对象和迭代器的关系,总觉得两个没有区别,这次再来一探究竟...

  • 迭代机制

    可迭代对象、迭代器、生成器、生成式区别 a. 可迭代对象: 一个对象能够被迭代的使用,这个对象就是可迭代对象 b....

  • 3-1 如何实现可迭代对象和迭代器对象(1)

    for循环的背后:确保in后边为可迭代对象 可迭代对象可以由内置函数iter得到一个迭代器对象注意:可迭代和迭代器...

  • Python 强化训练:第三篇

    强化训练:第三篇 问题来源 pythoner面试经常会问到迭代器和生成器的区别 内容 可迭代对象 迭代器:正向迭代...

  • Python中的可迭代对象和迭代器对象

    Python中的可迭代对象和迭代器对象是两种不同的东西,可迭代对象是Iterable,迭代器对象是Iterator...

  • Python基础-16生成器-迭代器

    16.生成器-迭代器     可循环迭代的对象称为可迭代对象,迭代器和生成器函数是可迭代对象,在Python中提供...

  • Python技巧:对象迭代与反迭代

    Welcome To My Blog 一.实现可迭代对象和迭代器 实例化iter()由可迭代对象得到迭代器通过给i...

网友评论

      本文标题:跟你深入剖析可迭代对象和迭代器的区别和联系

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