首先很多人一定不明白生成器yield是什么意思。其实和它最像的就是return。举个简单的例子吧。
return:的用法
def fib(n):
a=1
b=1
for i in range(0,n+1):
a,b=b,a+b
return a
print fib(10)
打印结果:
1
Process finished with exit code 0
看见了吗,只打印的第一个就直接返回了。也就是说循环才刚开始就直接退出该函数了。
yield:的用法
def fib(n):
a=1
b=1
for i in range(0,n+1):
a,b=b,a+b
yield a
for i in fib(10):
print i
打印结果:
1
2
3
5
8
13
21
34
55
89
144
Process finished with exit code 0
通过一个循环将fib的值返回值,反复打印。该函数每次产生一个值,函数就会被冻结,函数停在原地等待被重新被唤醒。函数被唤醒后就从定制的那点开始执行。(通过迭代来使用所有的值)
递归生成器。
def flatten(list):
try:
for i in list:
for j in flatten(i):
yield j
except TypeError:
yield list
print list(flatten([[1,[2,3],[[4,5],6]],7,8,[9,10]]))
打印结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Process finished with exit code 0
分析一下:
[1,[2,3],[[4,5],6]] 被变量 i 读取,而第二重循环导致 j 读取 刚那个列表里的第一个元素 1。1不是列表,引发类型错误。因为一个数字是不能被for 循环的。所以引发TypeError异常。此时的list是 那个 1. 则第一个元素 1 被迭代出来。
yield还是很好用的。比如输出一个杨辉三角。
杨辉三角长什么样子呢?
他有一个规律,每一行的 0+该行 加 该行+0 等于下一行的半边。
举个例子。第四行 1331 。01331 + 13310 = 14641 也就是下一行。
last 是上个列表的最后一行。
[sum(_) for _ in zip([0]+last,last+[0])] # 这就是上面的实现。
最后的生成结果。
[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]