解析Python中的生成器及其与迭代器的差异
生成器
生成器是一种迭代器,是一种特殊的函数,使用yield操作将函数构造成迭代器。普通的函数有一个入口,有一个返回值;当函数被调用时,从入口开始执行,结束时返回相应的返回值。生成器定义的函数,有多个入口和多个返回值;对生成器执行next()操作,进行生成器的入口开始执行代码,yield操作向调用者返回一个值,并将函数挂起;挂起时,函数执行的环境和参数被保存下来;对生成器执行另一个next()操作时,参数从挂起状态被重新调用,进入上次挂起的执行环境继续下面的操作,到下一个yield操作时重复上面的过程。Python的循环操作与C语言的实现不同,如果使用List等数据结构需要耗费大量的内容;循环操作中使用生成器只需要在内存中实例化一个对象,可以减少内存占用,提高循环操作的执行速度。
>>>defmyG(): ...yield1 ...yield2 ...yield3 ... >>>g=myG() >>>next(g) 1 >>>next(g) 2 >>>next(g) 3 >>>next(g) Traceback(mostrecentcalllast): File"<stdin>",line1,in<module> StopIteration >>>g2=myG() >>>foriing2: ...print(i) 1 2 3
生成器表达式
for...[if]...语句可以简洁的构建一个List,同时也可以用来构建生成器。
>>>a=[7,8,9] >>>b=[i**2foriina] >>>b [49,64,81] >>>ib=(i**2foriina) >>>ib <generatorobject<genexpr>at0x7f72291217e0> >>>next(ib) 49 >>>next(ib) 64 >>>next(ib) 81 >>>next(ib) Traceback(mostrecentcalllast): File"<stdin>",line1,in<module> StopIteration
迭代器(Iterator)与生成器(Generator)的区别
迭代器是一个更抽象的概念,任何对象,如果它的类有next方法(nextpython3)和iter方法返回自己本身。
每个生成器都是一个迭代器,但是反过来不行。通常生成器是通过调用一个或多个yield表达式构成的函数s生成的。同时满足迭代器的定义。
当你需要一个类除了有生成器的特性之外还要有一些自定义的方法时,可以使用自定义的迭代器,一般来说生成器更方便,更简单。
defsquares(start,stop): foriinxrange(start,stop): yieldi*i
等同于生成器表达式:
(i*iforiinxrange(start,stop))
列表推倒式是:
[i*iforiinxrange(start,stop)]
如果是构建一个自定义的迭代器:
classSquares(object): def__init__(self,start,stop): self.start=start self.stop=stop def__iter__(self): returnself defnext(self): ifself.start>=self.stop: raiseStopIteration current=self.start*self.start self.start+=1 returncurrent
此时,你还可以定义自己的方法如:
defcurrent(self): returnself.start
两者的相同点:对象迭代完后就不能重写迭代了。