python: yield, iterator...
时间:2010-08-12 来源:tiantian_0115
看到有很多人为yield写过blog. 其实我觉得就yield而言没有什么太多可以讲的。所以想把yield, generator, iterator一起来讲讲。
iterator, 这个就是一个对象,实现了函数__iter__()和next()的对象。他不需要继承什么父类,只需要实现这两个函数的对象我们就可以把它当作iterator来使用。如果要打印一串数,从0,1开始,后面的数是前面两个数的和(斐波那契数列)。这个时候我们可以很好的使用iterator来实现:
创建一个iterator类Fib,因为Fib类实现了函数__iter__()和next(),则被认为是一个iterator对象,可以通过for n in fib 来读取fib内的对象。每一次n都是从fib中取出一个值,然后再通过next函数取下面的值,一直这样下去。
class Fib: def __init__(self, max): self.max = max def __iter__(self): self.a = 0 self.b = 1 return self def next(self): fib = self.a if fib > self.max: raise StopIteration # 如果已经大于最大值则抛出StopIteration异常 self.a, self.b = self.b, self.a + self.b # 在return之前将self的值更新 return fib if __name__=="__main__": fib = Fib(1000) for n in fib: print n
在上面的代码中我们可以看到,next函数中,必须要申明fib变量来保存self.a的值,然后才可以将self.b的值付给self.a.
那如果我们使用yield返回来获得一个iterator则可以不用如此麻烦了,通过使用yield,fib函数可以认为是生成了一个generator. 这里我们每次返回了a以后,保留当前的状态继续执行 一直到函数结束。所以我们不需要什么临时值,只需要在返回a后再执行即可
def fib(max): a, b = 0, 1 while a < max: yield a a, b = b, a + b for n in fib(1000): print n
相比较list与iterator,可以知道iterator是不需要实现保存所有数据的,可以返回一个值处理一个。这样对于大数据量的时候可以节约很多内存。这大概就是在python3中range被xrange取代的原因吧。