简介
Python对延迟提供更多的支持,它提供了工具使得只有需要的时候才产生结果,而不是立即产生结果,从而节省了内存空间,并且允许计算时间分散到各个结果请求上。生成器函数和生成器表达式这有两种语言结构都尽可能地延迟结果的创建。
生成器函数
生成器函数编写为常规的def语句,但是使用yield语句一次返回一个结果。在每个结果之间挂起和继续它们的状态。生成器函数和常规函数之间的主要的代码不同在于,生成器yields一个值,而不是返回一个值。Yield语句挂起该函数并向调用者发送一个返回值,但是,保留足够的状态以使得函数能够从它离开的地方继续。当函数继续时,函数在上一个yield返回后立即继续执行。从函数的角度来看,这允许其代码随着时间产生一系列的值。
当调用生成器函数时,它们返回一个迭代器对象,该对象支持用一个名为__next__的自动创建的方法来继续执行的接口。生成器函数也可能有一个return语句,总是在def语句块的末尾,直接终止值的生成。从调用者角度来看,生成器的__next__方法继续函数并且运行到下一个yield结果或返回一个StopIteration异常。def gensquares(N):
for i in range(N):
yield i ** 2
if __name__ == '__main__':
for i in gensquares(5):
print(i, end=" : ")
输出结果为:
0 : 1 : 4 : 9 : 16 :
生成器表达式
从语法上讲, 生成器表达式就像一般的列表解析一样,但是它们是括在圆括号中而不是方括号中。返回结果的一个生成器对象,而不是创建一个结果列表。
生成器表达式大体上可以认为是对内存空间的优化,它们不需要想方括号的列表解析一样,一次构造出整个结果。它们在实际中运行起来可能稍慢一些,所以它们可能只对于非常大的结果集合的运算来说是最优的选择。
>>> G = (n ** 2 for n in range(5) )
>>> <generator obj
>>> G
ect <genexpr> at 0x0000000002C40BD0>
>>>
>>> next(G)
0
>>> next(G)
1