简介可迭代对象和迭代器是两个经常遇到但是很容易混淆的概念,所以今天就来和大家深入分析一下可迭代对象之间的区别迭代器和迭代器。仔细阅读本文后,您将获得:理解什么是可迭代对象理解检查可迭代对象的方法 理解什么是迭代器可迭代对象和迭代器的关系为时不晚,现在就开始吧!可迭代对象要理解可迭代对象,首先要理解迭代的概念。关于迭代,维基百科是这样定义的:迭代是重复反馈过程的活动,通常是为了接近并达到预期的目标或结果。过程的每一次重复称为一次“迭代”,每次迭代的结果作为下一次迭代的初始值。从这个定义中,我们大概可以知道,迭代就是对某个过程的重复。其实在程序中,迭代也是类似的,都是遍历集合元素的一种方式,请看下面的例子1。#例子1foriin[1,2,3]:print(i)outputresult:123In例1,解释器反复从列表中取出元素并打印,直到遍历结束,这是一个迭代的过程。可见,一个可迭代对象可以在for循环中遍历元素。那么什么样的对象是可迭代对象呢?其实只要实现了iter方法或者实现了__getitem__方法并且其参数从0开始索引,那么这个对象就是一个可迭代对象,见例2。#Example2classVector(object):def__init__(self,components):self.components=list(components)def__iter__(self):returniter(self.components)V1=Vector([1,2,3])foriinV1:print(i)output:123它可以从例2可以看出,Vector类实现了__iter__方法,解释器可以反复从Vector类对象中取出元素打印出来。如果要判断一个对象是否是可迭代对象,其实可以使用isinstance()函数,这个函数用来判断对象是否是某种类型,但是用这个函数判断不一定准确(原因会后面会提到)。fromcollections.abcimportIterableprint(isinstance(V1,Iterable))#True如果我们只是实现了__getitem__()方法呢?请参见示例3。#示例3fromcollections.abcimportIterableclassVector(object):def__init__(self,components):self.components=list(components)def__getitem__(self,index):returnself.components[index]V1=Vector([1,2,3])foriinV1:print(i)print(isinstance(V1,Iterable))输出结果:123Flase从例3可以看出,Vector实现了__getitem__方法,而解释器可以使用V1来迭代和打印元素,但是!在用isinstance()判断的时候,返回的结果其实是False。明明可以用for循环遍历元素,为什么会判断为False呢?实际上,如果iterable对象只实现了__getitem__,abc.Iterable并没有考虑这个方法,导致isinstance()判断不准确。更准确的方法应该是调用iter()函数。如果对象不可迭代,则会抛出TypeError错误。我们试试用iter()来判断。#Example4print(iter(V1))##去掉__getitem__方法后print(iter(V1))#TypeError:'Vector'objectisnotiterable从例子4可以看出,对于可用到迭代对象,iter()将返回。当__getitem__()方法被移除并再次检查时,会抛出TypeError错误。iter()函数用于生成一个迭代器,也就是说可以返回一个迭代器的是一个可迭代对象。该对象可以迭代,因为它实现了__iter__()方法。使用for循环时,解释器会检查对象是否有__iter__()方法,如果有,则调用它来获取迭代器。所以没有__iter__()方法但实现了__getitem__(),解释器会创建一个迭代器并尝试从0开始按顺序遍历元素。如果尝试失败,Python会抛出TypeError。那么Python内置类型中的可迭代对象有哪些呢?让我们一起盘点一下。Listdicttuplesetstring其实是统计序列的,所以任何序列都是可迭代对象,原因是它们至少会实现__getittem__方法(序列可以通过索引获取元素)。当迭代器引入可迭代对象时,在使用for循环时,解释器会检查对象是否有__iter__()方法,如果有则调用它得到一个迭代器。那么迭代器到底是什么?实际上,迭代器是一个实现了__iter__方法和__next__方法的对象。__iter__方法用于返回迭代器本身,而__next__用于返回下一个元素。我们自定义一个迭代器,以斐波那契数列为例说明其内部执行,见例5。#例5importitertoolsclassFib:def__init__(self):self.pre=0self.cur=1def__iter__(self):returnselfdef__next__(self):p=self.curself.cur+=self.preself.pre=preturnpf=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。#Example6>>>s='ABCD'>>>it=iter(s)>>>whileTrue:print(next(it))ABCD----------------------------------------------------------------------StopIterationTraceback(mostrecentcalllast)in()---->1whileTrue: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。#Example7fromcollections.abcimportIteratorf=Fib()print(isinstance(f,Iterator))#True说了这么多,迭代器有什么用呢?其实在Python语言内部,迭代器是用来支持:for循环构建和扩展集合类型逐行遍历文本文件列表推导、字典推导和集合推导关系型可迭代对象不一定是迭代器,迭代器必须是可迭代的对象。因为迭代器必须实现__iter__方法,而可迭代对象即使实现了__iter__也不一定实现__next__方法。Python从可迭代对象中获取迭代器。根据例6中的例子,我们知道我们首先使用iter()函数获取可迭代对象中的迭代器,然后使用next()获取下一个元素。关系如下图所示。总结可迭代对象实现了__iter__方法或实现了__getitem__方法,其参数从0开始索引。使用iter()函数可以更准确地判断可迭代对象。任何序列都是可迭代对象。迭代器对象实现了__iter__和__next__方法。迭代器是一种可以记住遍历位置的对象。里面有一个state记录迭代的位置,以便下次迭代时取出正确的元素。检查对象是否为迭代器的最佳方法是调用isinstance()方法。以上就是今天小编给大家分享的内容。如有任何疑问,请联系编辑,赶快扫描二维码关注吧。