带有 yield 的函数在 Python 中被称之为 generator(生成器)
deffab(max ) : n n,a,b=0,0,1 while nmax : yieldb # yield # print ba,b=b,an=n1forninfab(5) :打印yield
调用fab(5)不会执行fab函数,而是返回iterable对象。
执行for循环时,每个循环都会执行fab函数内部的代码,执行到yield b时,fab函数会返回迭代值,在下一次迭代时,代码会从yield b的以下语句继续执行
另一方面,函数的局部变量看起来与上次中断执行之前完全相同。 因此,函数继续执行,直到再次遇到yield。
也可以手动调用fab(5的next ) )方法。 这是因为fab ) (next ) )是具有方法的generator对象。 这样,fab的执行流程就会更加明确。
f=fab(5) f.next )、1 f.next )、1 f.next )、2 f.next )、3 f.next )、5 f.next )、traceback )、mostrecentcallllllet for循环不需要处理StopIteration异常,循环正常结束。
结论:
具有yield的函数是生成器。 与普通函数不同,generator看起来像函数调用,但在调用(next () )之前不会执行函数代码。 在for循环中自动为next ) ) ) ) )被调用后执行。 执行过程按照函数的过程执行,但每次执行yield语句时都会中断并返回迭代值,然后在下次执行时从yield的下一条语句继续执行。 它看起来就像函数在正常运行时被yield中断了几次一样。 每次中断时,yield都会返回当前的迭代值。
yield的优点很明显,将一个函数改写为一个generator可以获得迭代能力,与在类的实例中保存状态并计算下一个next )的值相比,不仅代码简洁,而且执行过程异常清晰。
如何判断某个函数是否为特殊的generator函数? 利用isgeneratorfunction可以确定以下内容:
请注意区分frominspectimportisgenerator functionisgeneratorfunction (fab ) truefab和fab )5)。 fab是生成函数,fab )5)是
importtypesisinstance(fab,types.GeneratorType ) fab )5),types.GeneratorType ) True fab不能重复
fromcollectionsimportIterableisinstance (fab,Iterable ) false isinstance (fab ) ),iterable ) true每次调用fab函数时都会出现新的generatiner
f1=fab(3) f2=fab(5)5) print 'f1: ',f1.next ) ) f1: 1 print 'f2: ',f2.next ) f 233601print ' f 1360 f2.next ) f2: f1.next(f1:1print ) f2: )、f2.next ) (f2:1print ) f1: )、f1.next ) f1:2print
在generator function中,如果没有return,则缺省情况下执行该函数直到函数完成,如果在执行过程中发生return,则直接抛出StopIteration以终止迭代。
另一个例子
另一个yield的例子来源于文件读取。 直接对文件对象调用read ()方法会导致不可预测的内存消耗。 好的方法是利用固定长度的缓冲区不断读取文件的内容。 使用yield,不需要创建读取文件的迭代类,从而使文件的读取变得简单。
defread_file(Fpath ) :block_size=1024withopen ) Fpath,' rb ' ) ASF : while true : block=f.read ) block