python的高级特性里,有一个生成器,能够实现边循环边计算机制。生成器的作用是什么呢?我的理解就是,用多少,去多少,避免浪费。下面会结合具体的例子,再做解释。
使用生成器有两种方式。
方式一
比较简单,把列表生成式的中括号改成小括号就可以了。
例如:
[x*x for x in range(1, 10)]
是一个列表生成式(list comprehensions),可以生成一个列表
[1, 4, 9, 16, 25, 36, 49, 64, 81]
那么
g = (x*x for x in range(1, 10))
就定义了一个生成器(generator)
然后不断调用next(g),就可以打印出列表中所有的值
>>> g = (x*x for x in range(1, 10))
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
但是一般不使用next()方法打印生成器的各个值,而是用循环的方式
>>> g = (x*x for x in range(1, 10))
>>> for n in g:\
... print(n)
...
1
4
9
16
25
36
49
64
81
方式二
使用yield()方法来替换print(),如杨辉三角的实现代码如下:
def triangles():
list = [1]
print(list)
n = 1
while(True):
tmp = [1]
for i in range(1, n):
tmp.append(list[i] + list[i-1])
tmp.append(1)
list = tmp
print(list)
n = n + 1
运行该方法,会不停的打印杨辉三角的每一行。如果把其中的print()改成yield(),
注意yield方法的作用是,每次执行到该方法就会中断,当下一次再调用时(next()),会从上次中断的位置继续执行。
def triangles():
list = [1]
yield(list)
n = 1
while(True):
tmp = [1]
for i in range(1, n):
tmp.append(list[i] + list[i-1])
tmp.append(1)
list = tmp
yield(list)
n = n + 1
n = 0
for t in triangles():
print(t)
n = n + 1
if n == 9:
break
此时的triangles就不再是一个函数,而是一个生成器了,打印结果如下:
[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]
那么生成器的作用体现在哪里呢?
方式一中的列表太小,好像看不出什么区别,但是如果要创建的list很大, 比如100万,而我们只需要前面的100个,那创建大小为 100万的list就是对内存的浪费了。有人要说了,我需要100个,我就直接写[x*x for x in range(1, 101)]不就可以了吗?不也能满足需求吗?但也许有时候我们需要100个,有时候我们需要200个,那么我们就要每次都重写一遍了。而用生成器的话,我们只用写一遍,比如g = (x*x for x in range(1, 1000000)),然后按照需要去取前面的多少个都可以。
方式二中的生成器也类似,它让我们获得了更多的灵活性,实现边循环边计算的效果。