生成器:generator,若list过大,不必创建完整的list,从而节省大量的空间。
方法一:把一个列表生成式的[]
改成()
,就创建了一个generator,通过next()
函数获得generator的下一个返回值。generator保存的是算法,每次调用next(g)
,就计算出g
的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration
的错误。
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>
>>> next(g)
0
>>> 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
>>> g = (x * x for x in range(10))
>>> for n in g:
... print(n)
...
0
1
4
9
16
25
36
49
64
81
方法二:如果一个函数定义中包含yield
关键字,那么这个函数就不再是一个普通函数,而是一个generator。关于yield理解:参照博客https://blog.csdn.net/lftaoyuan/article/details/78915518
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
练习:
错误:
def triangles():
a = [1]
while True:
yield a
b=a[:]
a.append(1)
if len(a) > 2:
for i in range(len(a)):
if i >= 1 and i < (len(a) - 1):
a[i] = b[i] + b[i - 1]
results = []
for t in triangles():
print(t)
results.append(t)
n = n + 1
if n == 10:
break
print(results)
if results == [
[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]
]:
print('测试通过!')
else:
print('测试失败!')
#这个地方,前面输出没有问题,result输出有问题(标记一下、不清楚是为什么)
修改后输出正确,测试通过:
def triangles():
a = [1]
while True:
b=a[:]
yield b
a.append(1)
if len(a) > 2:
for i in range(len(a)):
if i >= 1 and i < (len(a) - 1):
a[i] = b[i] + b[i - 1]
简化后:
def triangles():
a=[1]
while True:
b=a[:]
yield b
for i in range(len(a)-1):
a[i+1]=b[i]+b[i+1]
a.append(1)
网友究极进化版:
def triangles():
L = [1]
while True:
yield L
k = [L[i] + L[i + 1] for i in range(len(L) - 1)]
L = [1] + k + [1]