python之生成器

上文说道列表生成式,这节聊聊生成器

通过列表生成式可以很方便的创建一个了列表,但是受到内存的限制,列表容量肯定是有限的。而且创建一个包含100万元素的列表不仅占用很大的储存空间,如果我们只要访问前面几个元素占用的空间就白白浪费掉了

所以如果说列表的元素可以用一个算法推导出来,那我们不就可以在循环中不断推算出列表的元素,这样就可以不用创建完整的列表,从而节约大量的空间。在python中,一边循环一边计算的机制,称为:生成器(generator)

要创建一个生成器。有很多种方法,第一种方法很简单,只要把列表生成式的[]换成()就可以了。这样就创建一个生成器(generator)

#这一行错误主要是因为生成器必须有一个算式循环出来

那我们怎么才能输出生成器里的值呢,前面说过生成器是要用算法循环出来。我们可以调用next()函数输出

我们每次调用next()函数,计算出生成器L的值,直到最后一个元素,没有下一个元素抛出 StopIteration 错误。

当然上面不断调用next()函数的方法太没有效率了,我们说过生成器是一边循环一边计算。所以上面的例子要使用for循环

所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,而且不用担心StopIteration 错误。

生成器generator非常强大。如果推算的的算法比较复杂,用类似的列表生成式的 for 循环无法实现的时候,还可以用函数来实现

比如,著名的斐波拉契数列(Fibonacci),除了第一个数和第二个数之外,任意一个数都可以由前面两个数相加得到。

1,1,2,3,5,8,13,21,34,55,...

斐波拉契数列用列表生成式写不出来,但是用函数打印出来很容易

赋值语句:a,b = b,a+ b

相当于

t = (b, a + b) # t是一个tuplea = t[0]b = t[1]

上面的函数可以输出斐波拉契数列的前 n 个数

仔细观察,可以看出,fn函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator.

也就是说上面的函数和generator 仅有一步之遥,要想把fn函数变成生成器,只需要把 print(b) 换成 yield(b)就可以了

这样,函数就变成了一个生成器

这就是定义generator的另一种方法,如果一个函数中包含 yield 关键字,那么这个函数就不是普通的函数而是一个生成器generator

既然 fn 函数已经是一个生成器,我们用for循环来调用它

结果跟预想的一样。

但是我们发现了一个问题,在用for循环调用generator时,拿不到函数的返回值即return里的内容,想要拿到返回值必须捕获StopIteration中的值,我们调用next()函数来生成这个错误

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180715G0GEIF00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券