小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
生成器应该可以说是Python中最好用的特性之一了。 它是一个神奇的可以在运行过程中暂停的函数。或者这么说,它可以多次的返回值,具体来讲它会表现得如同迭代器一般(其实它就会变成一个迭代器,我们调用这个函数会得到生成器对象,而生成器对象就是属于迭代器,其值为函数依次产出的值,我们可以通过for循环等方式访问。) 生成器函数的形式是这样的:
def foo():
for i in range(10):
yield i
在这个函数中,函数会产出10个值,访问可以像下面这样:
for i in foo():
print(i)
基本用法就是这样,还有一个值得注意的地方就是,生成器函数的停止。生成器函数是用通过return语句停止的。上面的函数由于运行到结尾Python会给一个默认的return从而停止。而如果有必要的话,我们也可以控制在某处return以停止生成器。 有个这个东西,我们可以以一种很轻松的方式实现对象的可迭代性,因为生成器函数天生就是可以用来做迭代器。而且在每次调用它得到的是不同的生成器对象(这里也可以说是迭代器对象),同时它也更符合我们的思维方式。我们只需要在生成其中依次的做运算就行了,它yield的每个值就是迭代器中的值。所需要的状态可以保存在这次的函数中,而不是依赖于类中的字段。 假设有个数据需要外部只能迭代斐波拉契数列下标的项:
class A:
def __init__(self):
pass
def __iter__(self): # 这里就不真的取数据了,只返回个下标
yield 1
yield 1
f0,f1 = 1,1
while True:
f0, f1 = f1, f0 + f1
yield f1
为了让外部可以迭代,我们把生成器函数写在了iter方法上外部使用for会调用iter()函数。用于迭代并非生成器最大的用处,它真正的好处在于因为可以暂停函数的运行而带来的惰性求值的效果。 迭代只是为了使用它而实现的效果,而这无意间使得生成器函数成为了可迭代对象的简易实现方式。