迭代器和生成器
一、迭代器
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 += 1 f=Fibonacci(5) #f此时就是一个迭代器 for i in f: print(i)
2、可迭代对象
可迭代对象内部仅实现了__iter()__方法,可迭代对象可以通过._ iter _()方法转成迭代器。像list
、tuple
、dict
、set
、str等都是直接可以使用for循环的对象都是可迭代对象。
list=[1,2,3] #手动实现__iter__()方法 ilist=list.__iter__() print(ilist.__next__())#1 print(ilist.__next__())#2 print(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 3 t=test() print(type(t))#<class 'generator'> print(t.__next__())#1 print(t.__next__())#2 print(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+=1 f = 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 += 1 f=Fibonacci(5) #f此时就是一个迭代器 for i in f: print(i)
如何判断一个对象是可迭代对象呢?可以使用isinstance()进行判断。
from collections import Iterable print(isinstance([], Iterable))#True print(isinstance({}, Iterable))#True
如何判断是否是生成器对象?可以使用isgenerator()进行判断
from inspect import isgenerator def test(): yield 1 t=test() print(isgenerator(t))#True
详情查看:https://docs.python.org/3/library/inspect.html#inspect.isgeneratorfunction
如何判断是迭代器对象呢?可以使用isinstance()进行判断
from collections import Iterator a="abc" b=iter(a) print(type(b)) print(isinstance(b,Iterator))#True
总结:
迭代器对象内部实现了__iter__()和__next__()方法
可迭代对象仅实现__iter__()方法,必须依靠对象调用__iter__()方法(iter(o))才能成为迭代器对象
迭代器是可迭代对象,但可迭代对象不一定是迭代器。
生成器既是可迭代对象,又是迭代器对象,相当于xrange。