用过python的人都知道,在python中利用列表生成器能快速创建出一个列表。但是列表生成器也有它的局限性。其一就是有些复杂序列无法通过简单的列表生成器产生。其二就是当我们要生成的列表元素特别多时,摆在我们面前的将是内存浪费的问题。因为一旦列表生成,它需要占用一定的内存空间,当元素个数特别多时,内存占用不可忽略。特别是在我们只需求列表中的个别元素时,其他元素所占的空间就被白白浪费了。而生成器的提出正好解决了这两个问题。那什么是生成器呢?
生成器是一种能够根据所记录的算法边循环边推算出下一个元素的机制。生成器说白了就是一个函数,不过有别于普通函数,它的执行流程是不一样的。普通函数是顺序执行,遇到return语句或者函数的末尾句后返回。而生成器则是则在每次调用<font color=red>next()</font>函数时执行,遇到<font color=red>yield</font>关键字时返回。下一次从上次的<font color=red>yield</font>处继续执行。下面进行举例说明。
1. 简单的生成器
简单的生成器可以像列表生成器一样创建,只需要把[]改变成()即可:
l = [ x ** 2 for x in range(10)] # list comprehensions
g = ( x ** 2 for x in range(10)) # generator
我们可以查看g的type类型,发现它的类型是generator,并不是一个list。所以并没有占用大量的内存空间。我们可以用for循环来迭代我们的生成器g:
print(type(g))
for i in g:
print(i)
我们能看到如下的输出:
<type 'generator'>
0
1
4
9
16
25
36
49
64
81
2. 通过函数构建生成器
以著名的斐波那契数列为例介绍。斐波那契数列是一组前两个数字为1,其余的数字为数列中前两个数字和的序列。接下来我们用函数构造一个能够生成斐波那契数列的生成器:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
a, b = b, a + b
n += 1
yield a
return
同理,我们可以用for循环来打印出我们的数列:
f_g = fib(8)
print(type(f_g))
for i in f_g:
print(i, end=" ") # python3 method. If you want to used python2 need to import print_function from __future__
输出如下所示:
<type 'generator'>
1 1 2 3 5 8 13 21
python的生成器就介绍完了。为了体现python优雅的实现,我又在下面给出自己编写的另一个产生杨辉三角的生成器。不清楚杨辉三角的可以查看链接介绍。
def triangle():
L = [1]
while True:
yield L
L = [1] + [L[i] + L[i+1] for i in range(len(L)-1)] + [1]
下面是测试代码:
t = triangle()
for _ in range(12):
print(next(t))
输出:
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1]
[1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1]
网友评论