1. 创建生成器
1.1 方法一
只要把一个列表生成式的[ ]改成( ),就创建了一个generator:
>>> 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>
利用for循环可以打印出每个生成的值。
1.2 方法二
函数创建方法
比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
直接用函数方法如下:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
return 'done'
要把fib函数变成generator,只需要把print(b)改为yield b就可以了:
这里,需要注意的是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,是在每次调用next()的时候才执行,遇到yield语句就返回,再次执行时从上次返回的yield语句处继续执行。
并且调用该generator时,首先要生成一个generator对象,然后用next()函数不断获得下一个返回值:
2. 利用generator写杨辉三角
2.1 杨辉三角:
下图是杨辉三角的定义
请把每一行看做一个list,试写一个generator,不断输出下一行的list。
2.2 代码示例
def triangles():
result = [1]
while True: # 这是让每一调用都能进入到循环中
yield result # 这是每次调用的时候的打印结果
result = [1] + [x+y for x, y in zip(result[:-1], result[1:])] + [1] # 这是下一个result的结果,这里的zip很重要,下面单独讲讲zip
n = 0
results = []
for t in triangles():
print(t)
results.append(t)
n = n + 1
if n == 10:
break
# 输出结果是
[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]
2.3 zip
zip([iterable, …])
zip()是Python的一个内建函数,它接受一系列可迭代的对象作为参数,将对象中对应的元素打包成一个个tuple(元组),然后返回由这些tuples组成的list(列表)。
若传入参数的长度不等,则返回list的长度和参数中长度最短的对象相同。利用*号操作符,可以将list unzip(解压)。
2.3.1 把list使用zip创建一个元组对的列表
list1 = [1,2,3,4]
list2 = [5,6,7,8]
print zip(list1,list2)
#输出结果是 [(1, 5), (2, 6), (3, 7), (4, 8)]
2.3.2 利用for循环支持并行迭代
list1 = [1,2,3,4]
list2 = [5,6,7,8]
for (x,y) in zip(list1,list2):
print (x,y, "==",x+y)
# 输出结果是:
# (1, 5, '==', 6)
# (2, 6, '==', 8)
# (3, 7, '==', 10)
# (4, 8, '==', 12)