在进行for循环的时候,会碰到两个名词:一个是可迭代的对象iterable,一个是迭代器iterator。
可迭代的对象有很多,例如sequence中的string,list,tuple,还有字典dict,文件file等,在可迭代的对象中,主要是实现了__iter__()方法,从而使可迭代的。
迭代器iterator,在其中主要实现了方法__iter__()方法,和next()方法,所谓的迭代器也就是指具有next()方法的对象。在迭代器中的__iter__方法返回了一个可迭代的对象,当一个迭代器具有next方法的时候,那么就可以返回其自身,也就是return self。
可迭代的对象,也可以理解为可以使用for进行循环的对象。
迭代器是一个对象,迭代器的限制在于不能进行复制,不能从头开始。
判断一个类型是否是可以迭代的,可以使用isinstance方法,如下所示:
>>> from collections import Iterable >>> isinstance(list(),Iterable) True >>> isinstance('kel',Iterable) True >>> isinstance(tuple(),Iterable) True >>> isinstance(dict(),Iterable) True
创建迭代器主要使用以下方法:
iter(obj)在进行创建的时候,会查看obj是否是可迭代的,如果是可迭代的,那么将返回一个迭代器。
迭代的过程如下:
使用for循环来进行遍历——》根据next得到下一个值——》到达最后的时候触发异常Stopiteration——》for循环捕获异常——》循环结束
在迭代器中,只能够迭代一次,而在可迭代对象中,可以无限迭代,从而可以将数据和迭代进行分离,将数据保存在一个地方,将迭代器保存在另外一个地方,从而形成无限迭代,如下所示:
class Data(object): #用来保存数据的类 def __init__(self,*args): self.data = tuple(args) def __iter__(self): #可迭代的主要实现方法__iter__(self)方法 return DataIterable(self) class DataIterable(object): #迭代器的类 def __init__(self,data): self.data = data.data #注意初始化的时候,传递是是一个Data的实例,从而需要得到data的属性 self.index = 0 def __iter__(self): #迭代器直接返回自身,也就是返回具有next函数的迭代器的类 return self def next(self): #迭代器的主要方法next,不具有参数 if self.index == len(self.data): #遍历完所有的数据之后,抛出StopIteration的异常 raise StopIteration else: data = self.data[self.index] self.index += 1 return data if __name__ == '__main__': data = Data(1,'kel','xyz',4.56) for values in data: #可以进行无限迭代 print values for values in data: #第二次迭代 print values
内建的迭代器的函数:
1、 reversed()返回一个倒序的可迭代的对象
2、 enumerate()返回一个带有下标的迭代器
3、any()返回真当任何一个bool(x)为真
4、 all()返回真当所有的bool(x)为真
迭代器的真正好处在于只有在for循环的时候才计算得到的值,例如range函数和xrange函数:
>>> from collections import Iterable >>> isinstance(range(1),Iterable) True >>> isinstance(range(1),list) True >>> isinstance(xrange(1),Iterable) True >>> isinstance(xrange(1),list) False >>> range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> xrange(10) xrange(10以上表示,range生成的是一个列表,而xrange则是一个迭代器,从而在使用for循环的时候,range占用大量的内存,而xrange则是在循环的时候才得到值,从而比较节省内存,如下所示:
>>> import sys >>> sys.getsizeof(range(10000)) 80072 >>> sys.getsizeof(xrange(10000)) #可以看到xrange占用的内存很小,从而使用迭代器更加具有效率 40