关于python生成器
生成器 generator
定义:能够动态提供数据的可迭代对象。
关于动态的概念:循环一次,计算一次,返回一次。
作用:在循环过程中,按照某种算法推算数据,不需要创建容器存储完整的结果,从而节省内存空间。数据量越大,优势越明显。以上作用也称之为延迟操作或惰性操作,通俗的讲就是在需要的时候才计算结果,而不是一次构建出所有结果。
生成器函数
定义:含有yield语句的函数,返回值为生成器对象
语法
– 创建:
def 函数名():
…
yield 数据
…
– 调用:
for 变量名 in 函数名():
语句
说明:
– 调用生成器函数将返回一个生成器对象,不执行函数体。
– yield翻译为”产生”或”生成”。
执行过程:
(1) 调用生成器函数会自动创建迭代器对象。
(2) 在调用迭代器对象的__next__()方法时才执行生成器函数。
(3) 每次执行到yield语句时返回数据,暂时离开。
(4) 待下次调用__next__()方法时继续从离开处继续执行。
原理:生成迭代器对象的大致规则如下
– 将yield关键字以前的代码放在next方法中。
– 将yield关键字后面的数据作为next方法的返回值。
下面,我们可以写一些简单的例子,体会生成器函数在运行时的状态。
首先,我们稍微复习再上一篇文章中,通过创建迭代器对象的方法重写range函数。
需求:参照下列代码,自定义MyRange类,实现相同功能
for item in Myrange(n):
print(item)
class MyRange:
def __init__(self, end=0):
self.end = end
def __iter__(self):
return RangeIterator(self.end)
class RangeIterator:
def __init__(self, end=None):
self.end = end
self.__begin = -1
def __next__(self):
self.__begin += 1
if self.__begin > self.end - 1:
raise StopIteration
return self.__begin
#test
for i in MyRange(5):
print(i)
输出的结果是0,1,2,3,4。
这里我们只是进行简单的重写,并没有再现Range函数中定义起点和步进的功能。
下面,我们通过生成器对自定义函数MyRange进行再重写:
def MyRange(end=0):
number = 0
while number < end:
yield number
number += 1
#test
for i in MyRange(5):
print(i)
得到的结果同样是 0,1,2,3,4。
对比上面两段代码,实现相同的功能,代码量和运行时所占用的内存大小也不一样。
在此,稍微穿插迭代器协议。
迭代器协议
迭代器协议指的是对象必须提供一个__next__方法,执行时要么返回迭代中的下一项,要么引起StopIteration异常使得迭代终止。
可迭代对象:实现了迭代器协议的对象。在python中,我们平时使用的for循环就是通过迭代器协议访问对象。
总结
在实际工作应用中,充分利用python的生成器能够减少内存的占用,还能提高代码可读性。希望这篇小笔记能够让读者对生成器有所理解,也希望能够指出我的不足之处。