一、迭代器
1、定义
迭代器(Iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。
满足什么样的条件才能成为迭代器呢?
- 必须遵从迭代器协议
迭代器协议:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 。
满足什么样条件的对象才能提供一个next方法呢?
- 对象内部定义一个__iter__()以及__next__()方法
class Fibonacci(object): def __init__(self,m): self.m=m def __iter__(self): return self #自身是一个迭代器 def __next__(self): n, a, b = 0, 0, 1 while n < self.m: print(b) a, b = b, a + b n += 1f=Fibonacci(5) #f此时就是一个迭代器for i in f: print(i)
如果对象调用__iter__()方法,调用后对象也可以提供一个__next__()方法,但是这样的对象只能被称为可迭代对象(Iterable),因为它不是对象内动实现__iter__()方法,内部自动实现__iter__()方法的对象,才能被称为迭代器(Iterator)。
2、可迭代对象
可迭代对象与迭代器对象的区别就是看__iter()__方法是不是在对象内部实现的,如果是内部实现的就是迭代器对象,共同点就是都实现了迭代器协议(对象提供了next方法)。
像list
、tuple
、dict
、set
、str等都是直接可以使用for循环的对象都是可迭代对象,使用的就是迭代器协议,但是__iter__()方法是依靠for循环来实现的。
list=[1,2,3]#手动实现__iter__()方法ilist=list.__iter__() print(ilist.__next__())#1print(ilist.__next__())#2print(ilist.__next__())#3
而在for循环内部也是基于这样的实现方式,不过在for循环内部还进行了异常处理。
#####for循环的实质#######list=[1,2,3]#手动实现__iter__()方法ilist=list.__iter__()while True: try: print(ilist.__next__()) except StopIteration as e: break
3、生成器
可以理解为一种数据类型,这种数据类型自动实现了迭代器协议,即内部自动实现了__iter__()方法,提供了__next__()方法,所以生成器不仅是可迭代对象而且还是迭代器对象。那么所有可迭代对象拥有的特性,它都拥有,比如for循环。
如何构造一个生成器呢?
在一个函数中通过yield关键字自动创建一个生成器函数,yield
会自动构建好__next__()和__iter__()方法。
def test(): yield 1 yield 2 yield 3t=test()print(type(t))#print(t.__next__())#1print(t.__next__())#2print(t.__next__())#3
进行for循环
for i in test(): print(i) #1,2,3
所以生成器就是迭代器的一种,是构造迭代器的工具。
def Fibanocci(m): n,a,b = 0,0,1 while n < m: yield b a,b=b,a+b n+=1f = Fibanocci(5) #f为一个迭代器对象,可以将其当作xrange来对待while True: try: print(f.__next__()) except StopIteration as e: break
在类中也是可以实现迭代器的:
class Fibonacci(object): def __init__(self,m): self.m=m def __iter__(self): n, a, b = 0, 0, 1 while n < self.m: yield b a, b = b, a + b n += 1f=Fibonacci(5) #f此时就是一个迭代器for i in f: print(i)
如何判断一个对象是可迭代对象呢?可以使用isinstance()进行判断。
from collections import Iterableprint(isinstance([], Iterable))#Trueprint(isinstance({}, Iterable))#True
如何判断是否是生成器对象?可以使用isgenerator()进行判断
from inspect import isgeneratordef test(): yield 1t=test()print(isgenerator(t))#True
详情查看:
如何判断是迭代器对象呢?可以使用isinstance()进行判断
from collections import Iteratora="abc"b=iter(a)print(type(b))print(isinstance(b,Iterator))#True
总结:
迭代器对象内部实现了__iter__()方法以及实现了__next__()方法
可迭代对象内部没有实现__iter__()方法,必须依靠对象调用__iter__()方法(iter(o))才能成为迭代器对象
生成器既是可迭代对象,又是迭代器对象,相当于xrange。