python源代码中经常会有使用yield,带有yield的函数是generator(生成器),它返回是一个迭代值,下面我们分析yield是什么原理,有什么好处?
首先,我们写一个简单的斐波那契数列前n项值得方法:
def fab(max): n,a,b=0,0,1 while n<max: print b a,b=b,a+b n=n+1 fab(5) input()
函数输出1 1 2 3 5 没有问题,但是该方法没有返回值,复用性太差了,我们希望得到有返回结果的方法。
修改如下:
def fab(max): n,a,b=0,0,1 result=[] while n<max: result.append(b) a,b=b,a+b n=n+1 return result print fab(5) input()
返回[1,1,2,3,5]的list,这样我们就可以方便的用它的结果了,但是当max很大时,对内存是一个很大的开销,并不是一个好的方法,怎么办呢?这就要用到迭代器的知识了,返回一个迭代变量是更好的选择。
例如 for i in range(100):pass 会导致生成一个100个元素的list;
for i in xrange(100):pass 不会产生100个元素的list,而是每次返回一个iterable对象,只有上一个数据用完之后才生成下一个,每次只返回一个,所以减小了内存开销。
利用iterable我们可以把fab()方法写成一个支持iterable的class,如下:
class Fab(object): def __init__(self,max): self.max=max self.n,self.a,self.b=0,0,1 def __iter__(self): return self def next(self): if self.n<self.max: r=self.b self.a,self.b=self.b,self.a+self.b self.n=self.n+1 return r raise StopIteration() fab=Fab(5) for n in fab: print n input()
这样就实现了迭代器的返回方法,但是代码太多,不够简洁,这时候yield就用上了。
def fab(max): n,a,b=0,0,1 while n<max: yield b a,b=b,a+b n=n+1 for i in fab(5): print i input()
这样就实现了。
yeild的原理:一个带有yield的函数就是一个generator生成器,和普通的函数不一样。只有调用next()函数的时候才会执行函数语句,在for循环中会自动调用next()方法。函数执行过程中遇到一个yield会中断一次,返回一个迭代值,函数保存自己的变量和状态,下次迭代时(也就是下次next()的时候)从yield下一条语句继续执行(这个性质很重要),函数恢复之前状态,直到遇到下一个yield返回迭代值,这样循环。
可以用
f=fab(5)
fab.next()不断测试来分析它的原理。